Re-index data frame; fill index using elements from multiple columns - python

I have a Pandas DataFrame as shown below:
I1 V1 I2 V2 I3 V3 ...
0 13.823560 0.000000 13.639405 0.000000 13.455246 0.000000 ...
1 13.823376 0.001274 13.639224 0.001273 13.455068 0.001272 ...
2 13.823193 0.002547 13.639043 0.002546 13.454889 0.002544 ...
3 13.823009 0.003821 13.638862 0.003819 13.454711 0.003817 ...
4 13.822826 0.005095 13.638681 0.005092 13.454532 0.005089 ...
5 13.822642 0.006368 13.638500 0.006365 13.454354 0.006361 ...
... ... ... ... ... ... ... ...
495 0.613282 0.630456 0.610912 0.630109 0.608497 0.629756 ...
496 0.455202 0.631730 0.453456 0.631381 0.451677 0.631028 ...
497 0.296663 0.633004 0.295533 0.632654 0.294383 0.632301 ...
498 0.137670 0.634277 0.137149 0.633927 0.136619 0.633573 ...
499 -0.021770 0.635551 -0.021688 0.635200 -0.021605 0.634845 ...
[500 rows x 120 columns]
What I would like to do is reshape the DataFrame to make it look like this:
#(I as new index)
I V1 V2 V3 ...
13.823560 0.000000 NaN NaN ...
13.823376 0.001274 NaN NaN ...
13.823193 0.002547 NaN NaN ...
13.823009 0.003821 NaN NaN ...
13.822642 0.005095 NaN NaN ...
... ... ... ... ...
0.137670 0.630456 NaN NaN ...
0.136619 NaN NaN 0.633573 ...
-0.021605 NaN NaN 0.634845 ...
-0.021688 NaN 0.635200 NaN ...
-0.021770 0.635551 NaN NaN ...
[30000 rows x 60 columns]
In other words, I want to fill the new DataFrame index with all values encountered in all "I"-labeled columns (1 to 60 in my case). However, I also want to keep the remaining V-columns untouched for now - as long as they still link to their original I-counterpart value.
When trying the following ...
dfen = pd.melt(dfen, id_vars=['I'+str(b) for b in xrange(1,len(irlist)+1)], var_name='id', value_name='V')
... the DataFrame is squeezed to just two columns, so I think I will need something trickier.
Anyone any idea how to re-index the DataFrame in the way shown above?
The function will be called a lot of times, so speed optimization is quite important as well.

Starting with:
Int64Index: 11 entries, 0 to 10
Data columns (total 6 columns):
I1 11 non-null float64
V1 11 non-null float64
I2 11 non-null float64
V2 11 non-null float64
I3 11 non-null float64
V3 11 non-null float64
dtypes: float64(6)
Try:
pd.concat([df.loc[:, ['V{}'.format(i), 'I{}'.format(i)]].rename(columns={'I{}'.format(i): 'I'}) for i in range(1, 4)])
to get:
I V1 V2 V3
0 13.823560 0.000000 NaN NaN
1 13.823376 0.001274 NaN NaN
2 13.823193 0.002547 NaN NaN
3 13.823009 0.003821 NaN NaN
4 13.822826 0.005095 NaN NaN
5 13.822642 0.006368 NaN NaN
6 0.613282 0.630456 NaN NaN
7 0.455202 0.631730 NaN NaN
8 0.296663 0.633004 NaN NaN
9 0.137670 0.634277 NaN NaN
10 -0.021770 0.635551 NaN NaN
0 13.639405 NaN 0.000000 NaN
1 13.639224 NaN 0.001273 NaN
2 13.639043 NaN 0.002546 NaN
3 13.638862 NaN 0.003819 NaN
4 13.638681 NaN 0.005092 NaN
5 13.638500 NaN 0.006365 NaN
6 0.610912 NaN 0.630109 NaN
7 0.453456 NaN 0.631381 NaN
8 0.295533 NaN 0.632654 NaN
9 0.137149 NaN 0.633927 NaN
10 -0.021688 NaN 0.635200 NaN
0 13.455246 NaN NaN 0.000000
1 13.455068 NaN NaN 0.001272
2 13.454889 NaN NaN 0.002544
3 13.454711 NaN NaN 0.003817
4 13.454532 NaN NaN 0.005089
5 13.454354 NaN NaN 0.006361
6 0.608497 NaN NaN 0.629756
7 0.451677 NaN NaN 0.631028
8 0.294383 NaN NaN 0.632301
9 0.136619 NaN NaN 0.633573
10 -0.021605 NaN NaN 0.634845

Related

How to filter column based on another column date range

I currently have a dataframe where 1st column is dates (1990 - 2020) and the subsequent columns are 'stocks' that are trading and are NaN if they are not yet being traded. Is there any way to filter the columns based on date range? For example, if 2 years is selected, all stocks that are not null in all columns from 2019-2020 (2 years) will be filtered in.
import pandas as pd
df = pd.read_csv("prices.csv")
df.head()
display(df)
date s_0000 s_0001 s_0002 s_0003 s_0004 s_0005 s_0006 s_0007 s_0008 ... s_2579 s_2580 s_2581 s_2582 s_2583 s_2584 s_2585 s_2586 s_2587 s_2588
0 1990-01-02 NaN 13.389421 NaN NaN NaN NaN NaN 0.266812 NaN ... NaN 1.950358 NaN 7.253997 NaN NaN NaN NaN NaN NaN
1 1990-01-03 NaN 13.588601 NaN NaN NaN NaN NaN 0.268603 NaN ... NaN 1.985185 NaN 7.253997 NaN NaN NaN NaN NaN NaN
2 1990-01-04 NaN 13.610730 NaN NaN NaN NaN NaN 0.269499 NaN ... NaN 1.985185 NaN 7.188052 NaN NaN NaN NaN NaN NaN
3 1990-01-05 NaN 13.477942 NaN NaN NaN NaN NaN 0.270394 NaN ... NaN 1.985185 NaN 7.188052 NaN NaN NaN NaN NaN NaN
4 1990-01-08 NaN 13.477942 NaN NaN NaN NaN NaN 0.272185 NaN ... NaN 1.985185 NaN 7.385889 NaN NaN NaN NaN NaN NaN
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
7806 2020-12-23 116.631310 22.171579 15.890000 16.577030 9.00 65.023491 157.495850 130.347580 27.481012 ... 19.870001 42.675430 2.90 8.850000 9.93 NaN 0.226 207.470001 158.974014 36.650002
7807 2020-12-24 116.641243 21.912146 15.660000 16.606722 8.77 65.292725 158.870193 131.352829 27.813406 ... 20.180000 42.508686 2.88 8.810000 9.91 NaN 0.229 205.270004 159.839264 36.009998
7808 2020-12-28 117.158287 22.191536 16.059999 16.200956 8.93 66.429459 157.011383 136.050766 28.272888 ... 19.959999 42.528305 2.69 8.760000 9.73 NaN 0.251 199.369995 161.500122 36.709999
7809 2020-12-29 116.561714 21.991972 15.860000 16.745275 8.80 66.529175 154.925140 134.239273 27.705866 ... 19.530001 41.949623 2.59 8.430000 9.61 NaN 0.243 197.839996 162.226105 36.610001
7810 2020-12-30 116.720795 22.899990 16.150000 17.932884 8.60 66.299828 155.884232 133.094650 27.725418 ... 19.870001 42.390987 2.65 8.540000 9.72 NaN 0.230 201.309998 163.369812 36.619999
so I want to do something like:
year = input(Enter number of years:)
year = 3
If year is 3, the daterange selected would be 3 years to 2020 (2018-2020)
You could try the following code:
df[(df['date'] >= '2019-01-01') & (df['date'] <= '2020-12-30')]
Once you filter, you could remove all rows, which include NaN:
df.dropna()

Replace dataframe values by NaN

I am working with a pandas dataframe of 15 rows and 8 columns, such a:
A B ... G H
0 0.158979 0.187282 ... 0.330566 0.458748
1 0.227254 0.273307 ... 0.489372 0.649698
2 0.308775 0.351285 ... 0.621399 0.833404
3 0.375850 0.444228 ... 0.759206 0.929980
4 0.431860 0.507906 ... 0.850741 1.038544
5 0.507219 0.596291 ... 0.980404 1.145819
6 0.570170 0.676551 ... 1.094201 1.282077
7 0.635122 0.750434 ... 1.155645 1.292930
8 0.704220 0.824748 ... 1.261516 1.395316
9 0.762619 0.887669 ... 1.337860 1.410864
10 0.824553 0.968889 ... 1.407665 1.437886
11 0.893413 1.045289 ... 1.519902 1.514017
12 0.946757 1.109964 ... 1.561611 1.478634
13 1.008294 1.174139 ... 1.596135 1.501220
14 1.053086 1.227203 ... 1.624630 1.503892
where columns from C to F have been omitted.
I would like to know how I can find the closest value to 1 for every column. Once this value is found I would like to replace the rest of the values in the columns by NaN, with the exception of the values corresponding to the previous and next row. Then obtaining a dataframe like that:
A B ... G H
0 NaN NaN ... NaN NaN
1 NaN NaN ... NaN NaN
2 NaN NaN ... NaN NaN
3 NaN NaN ... NaN 0.929980
4 NaN NaN ... 0.850741 1.038544
5 NaN NaN ... 0.980404 1.145819
6 NaN NaN ... 1.094201 NaN
7 NaN NaN ... NaN NaN
8 NaN NaN ... NaN NaN
9 NaN 0.887669 ... NaN NaN
10 NaN 0.968889 ... NaN NaN
11 NaN 1.045289 ... NaN NaN
12 0.946757 NaN ... NaN NaN
13 1.008294 NaN ... NaN NaN
14 1.053086 NaN ... NaN NaN
Does anyone has a sugestion for this?
Thanks in advance
you can use the fact that the closest to 1 is actually the min of the abs of df once remove 1. So check where the min is meet, use shift once with 1 and once with -1 to get the next and previous row. use this mask in where.
df_ = (df-1).abs()
df_ = df_.min() == df_
df_ = df_|df_.shift(1)|df_.shift(-1)
df_ = df.where(df_)
print(df_)
A B G H
0 NaN NaN NaN NaN
1 NaN NaN NaN NaN
2 NaN NaN NaN NaN
3 NaN NaN NaN 0.929980
4 NaN NaN 0.850741 1.038544
5 NaN NaN 0.980404 1.145819
6 NaN NaN 1.094201 NaN
7 NaN NaN NaN NaN
8 NaN NaN NaN NaN
9 NaN 0.887669 NaN NaN
10 NaN 0.968889 NaN NaN
11 NaN 1.045289 NaN NaN
12 0.946757 NaN NaN NaN
13 1.008294 NaN NaN NaN
14 1.053086 NaN NaN NaN

How to delete a column out of a pandas pivot table? (Python)

I have a pandas dataframe like this:
In [31]: df.pivot(index='orderid', columns='C', values='productid')
Out [31]:
C 1 2 3 4 5 6 7 8 9 10 ... 71 72 73 74 75 76 77 78 79 80
orderid
20000765 624380 nan nan nan nan nan nan nan nan nan ... nan nan nan nan nan nan nan nan nan nan
20000766 624380 nan nan nan nan nan nan nan nan nan ... nan nan nan nan nan nan nan nan nan nan
20000768 1305984 1305985 1305983 1306021 nan nan nan nan nan nan ... nan nan nan nan nan nan nan nan nan nan
I would like to delete the first column. However, when I do that the table unpivots again.
What I can I do to delete the "C" / "Orderid" column and the numbers underneath it?

Converting pd.read_sql_query to pd.DataFrame converts strings to nan

When I try to take an SQL Query generated from a pd.read_sql_query to a dataframe using pd.DataFrame my string values get converted to nan.
I tried using dtypes to set the type of each column
SQL_Query = pd.read_sql_query('''SELECT [CircuitID], [Status],
[LatestJiraTicket], [MrcNew]
FROM CircuitInfoTable
WHERE ([Status] = 'Active')
OR ([Status] = 'Pending')
OR ([Status] = 'Planned')''', conn)
# print(SQL_Query)
cdf = pd.DataFrame(SQL_Query, columns=['CID', 'Status', 'JiraTicket', 'MrcNew'])
SQL Query output:
0 OH1004-01 ... NaN
1 OH1004-02 ... NaN
2 OH1005-01 ... NaN
3 OH1005-02 ... NaN
4 AL1001-01 ... NaN
5 AL1001-02 ... NaN
6 AL1007-01 ... NaN
7 AL1007-02 ... NaN
8 NC1001-01 ... NaN
9 NC1001-02 ... NaN
10 NC1001-03 ... NaN
11 NC1001-04 ... NaN
12 NC1001-05 ... NaN
13 NC1001-06 ... NaN
14 (ommited on purpose) ... 5200.0
15 MO001-02 ... NaN
16 OR020-01 ... 8000.0
17 MA004-01 ... 6500.0
18 MA004-02 ... 6500.0
19 OR004-01 ... 10500.0
20 (ommited on purpose) ... 3975.0
21 OR007-01 ... 2500.0
22 (ommited on purpose) ... 9200.0
23 (ommited on purpose) ... 15000.0
24 (ommited on purpose) ... 5750.0
25 CA1005-02 ... 47400.0
26 CA1005-03 ... 47400.0
27 CA1005-04 ... 47400.0
28 CA1005-05 ... 47400.0
29 CA1006-01 ... 0.0
DataFrame output:
CID Status JiraTicket MrcNew
0 nan Planned nan NaN
1 nan Planned nan NaN
2 nan Planned nan NaN
3 nan Planned nan NaN
4 nan Planned nan NaN
5 nan Planned nan NaN
6 nan Planned nan NaN
7 nan Planned nan NaN
8 nan Planned nan NaN
9 nan Planned nan NaN
10 nan Planned nan NaN
11 nan Planned nan NaN
12 nan Planned nan NaN
13 nan Planned nan NaN
14 nan Active nan 5200.0
15 nan Pending nan NaN
16 nan Pending nan 8000.0
17 nan Pending nan 6500.0
18 nan Pending nan 6500.0
19 nan Pending nan 10500.0
20 nan Active nan 3975.0
21 nan Pending nan 2500.0
22 nan Active nan 9200.0
23 nan Pending nan 15000.0
24 nan Active nan 5750.0
25 nan Pending nan 47400.0
26 nan Pending nan 47400.0
27 nan Pending nan 47400.0
28 nan Pending nan 47400.0
29 nan Pending nan 0.0
Basically, you are using columns argument incorrectly in pandas.DataFrame where that arugment specifies columns to select in resulting output (not to rename). From your query there is no CID or JiraTicket and hence they migrate with all missing values.
Possibly you intended to rename columns. Consider renaming in either SQL with column aliases or in pandas with rename or set_axis:
SELECT [CircuitID] AS [CID],
[Status],
[LatestJiraTicket] AS JiraTicket,
[MrcNew]
FROM CircuitInfoTable
WHERE ([Status] = 'Active')
OR ([Status] = 'Pending')
OR ([Status] = 'Planned')
Pandas
cdf = (pd.read_sql_query(...original query...)
.rename(columns={'CircuitID': 'CID', 'LatestJiraTicket': 'JiraTicket'})
)
cdf = (pd.read_sql_query(...original query...)
.set_axis(['CID', 'Status', 'JiraTicket', 'MrcNew'], axis='columns', inplace=False)
)

Subtracting column from dataframe

Hi I'm trying to subtract values of one of DataFrame columns from whole DataFrame. Intuitively this seems like a non-problem for me, but somehow I can't figure it out.
Here is the code:
import pandas as pd
x = pd.DataFrame({
"a": range(1, 10),
"b": range(2, 11),
"c": range(11, 20)
})
print x - x['b']
And what I get is surprisingly:
0 1 2 3 4 5 6 7 8 a b c
0 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
1 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
3 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
4 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
5 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
6 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
7 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
8 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
Instead of DataFrame with columns: (a-b), (b-b), (c-b).
I just started playing with Python. Can you tell me what am I missing?
Thanks!
Try:
x.subtract(x['b'], axis=0)
a b c
0 -1 0 9
1 -1 0 9
2 -1 0 9
3 -1 0 9
4 -1 0 9
5 -1 0 9
6 -1 0 9
7 -1 0 9
8 -1 0 9
See docs for details on the axis=0 parameter, which ensures that the index of x['B'] aligns with the DataFrame index, and not the columns as per default.
To make the - operator work, you'd have to:
(x.T - x['b']).T

Categories