Suppose that I have a timeseries like
In [41]: df = pd.DataFrame(dict(names=list('abcaabcabbcc'), vals=np.random.randint(0, 10, 12)), index
...: =pd.date_range('2017-03-01', periods=12))
In [42]: df
Out[42]:
names vals
2017-03-01 a 2
2017-03-02 b 9
2017-03-03 c 6
2017-03-04 a 6
2017-03-05 a 5
2017-03-06 b 2
2017-03-07 c 3
2017-03-08 a 1
2017-03-09 b 1
2017-03-10 b 1
2017-03-11 c 1
2017-03-12 c 0
How can I convert the names row into the column headers, under which the corresponding vals are? e.g.
a b c
2017-03-01 2 nan nan
2017-03-02 nan 9 nan
...
I have been playing around with pd.melt as well as trying to add the names to the index and then reset the index so that they become columns somehow, but I am very stuck.
You can use:
print (pd.pivot(index=df.index, columns=df['names'], values=df['vals']))
Or:
print (df.set_index('names', append=True)['vals'].unstack())
names a b c
2017-03-01 4.0 NaN NaN
2017-03-02 NaN 0.0 NaN
2017-03-03 NaN NaN 3.0
2017-03-04 8.0 NaN NaN
2017-03-05 0.0 NaN NaN
2017-03-06 NaN 0.0 NaN
2017-03-07 NaN NaN 9.0
2017-03-08 6.0 NaN NaN
2017-03-09 NaN 6.0 NaN
2017-03-10 NaN 0.0 NaN
2017-03-11 NaN NaN 3.0
2017-03-12 NaN NaN 9.0
print (df.reset_index().pivot_table(index='index', columns='names', values='vals'))
you can also use unstack():
In [12]: df.set_index('names', append=True).unstack('names')
Out[12]:
vals
names a b c
2017-03-01 1.0 NaN NaN
2017-03-02 NaN 4.0 NaN
2017-03-03 NaN NaN 5.0
2017-03-04 8.0 NaN NaN
2017-03-05 8.0 NaN NaN
2017-03-06 NaN 5.0 NaN
2017-03-07 NaN NaN 7.0
2017-03-08 5.0 NaN NaN
2017-03-09 NaN 7.0 NaN
2017-03-10 NaN 4.0 NaN
2017-03-11 NaN NaN 3.0
2017-03-12 NaN NaN 4.0
Related
I've been looking for the way to remove NaN in each row of dfA(DataFrame) and after then, move every row under push1_start_date and reconnect with the end of push1_start_date. Is it possible to do that ?? I tried stack() and unstack() method but it doesn't work .Thank you.
push1_start_date push2_start_date push3_start_date push4_start_date push5_start_date push6_start_date push7_start_date push8_start_date
2021-04-29 3 NaN NaN NaN NaN NaN NaN NaN
2021-04-30 20 NaN NaN NaN NaN NaN NaN NaN
2021-05-01 24 NaN NaN NaN NaN NaN NaN NaN
2021-05-02 21 NaN NaN NaN NaN NaN NaN NaN
2021-05-03 14 NaN NaN NaN NaN NaN NaN NaN
2021-05-04 5 NaN NaN NaN NaN NaN NaN NaN
2021-05-05 14 NaN NaN NaN NaN NaN NaN NaN
2021-05-06 16 NaN NaN NaN NaN NaN NaN NaN
2021-05-07 17 NaN NaN NaN NaN NaN NaN NaN
2021-05-08 14 NaN NaN NaN NaN NaN NaN NaN
2021-05-11 78 NaN NaN NaN NaN NaN NaN NaN
2021-05-12 20 78.0 NaN NaN NaN NaN NaN NaN
2021-05-13 13 21.0 NaN NaN NaN NaN NaN NaN
2021-05-14 8 12.0 NaN NaN NaN NaN NaN NaN
2021-05-15 18 8.0 NaN NaN NaN NaN NaN NaN
2021-05-16 16 19.0 NaN NaN NaN NaN NaN NaN
2021-05-17 16 16.0 NaN NaN NaN NaN NaN NaN
2021-05-18 18 15.0 NaN NaN NaN NaN NaN NaN
2021-05-19 14 19.0 NaN NaN 1.0 2.0 NaN NaN
2021-05-20 13 14.0 1.0 NaN 1.0 1.0 NaN NaN
2021-05-21 11 13.0 NaN NaN 1.0 NaN 1.0 NaN
2021-05-22 26 10.0 NaN 2.0 NaN 1.0 NaN NaN
2021-05-23 12 27.0 NaN 1.0 NaN NaN NaN NaN
2021-05-24 15 12.0 1.0 3.0 NaN 1.0 NaN NaN
2021-05-25 9 16.0 NaN 1.0 NaN 1.0 NaN NaN
2021-05-26 14 9.0 NaN 1.0 NaN NaN NaN NaN
2021-05-27 14 12.0 NaN NaN NaN NaN NaN NaN
2021-05-28 21 16.0 NaN NaN NaN NaN NaN NaN
2021-05-29 23 20.0 1.0 2.0 1.0 1.0 NaN NaN
2021-05-30 18 23.0 1.0 NaN 1.0 1.0 NaN NaN
2021-05-31 19 17.0 NaN 3.0 1.0 3.0 NaN NaN
2021-06-01 15 21.0 NaN 3.0 1.0 1.0 NaN NaN
2021-06-02 22 13.0 1.0 2.0 NaN 1.0 NaN NaN
2021-06-03 19 23.0 1.0 NaN NaN 1.0 NaN NaN
2021-06-04 12 20.0 2.0 NaN 2.0 NaN NaN NaN
2021-06-05 2 1.0 NaN NaN NaN 1.0 NaN NaN
ideal output
push1_start_date
2021-04-29 3 ←The begging of push1_start_date
2021-06-05 2 ←The last of push1_start_date
2021-05-12 78 ←The begging of push2_start_date
2021-06-05 1.0 ←The last of push2_start_date
2021-05-20 1.0 ←The begging of push2_start_date
2021-06-04 2.0 ←The last of push2_start_date
it comtines untill push8_start_date
You can try with reset_index(), melt(),dropna() and drop():
out=(df.reset_index()
.melt('index',value_name='push_start_date')
.dropna(subset=['push_start_date'])
.drop('variable',1))
OR
via concat() and to_frame():
out=(pd.concat([df[x].dropna() for x in df.columns[df.dtypes!='object']])
.to_frame('push_start_date'))
You could use df.melt() to stack all the columns on the right into 1 column, then keep only the value column without null values:
df.melt().drop('variable', axis=1).dropna()
Output
value
2021-04-29 3
... ...
2021-06-05 2
2021-05-12 78
... ...
2021-06-05 1.0
2021-05-20 1.0
... ...
2021-06-04 2.0
... ...
I want to convert below dataframe,
ID TYPE A B
0 1 MISSING 0.0 0.0
1 2 1T 1.0 2.0
2 2 2T 3.0 4.0
3 3 MISSING 0.0 0.0
4 4 2T 10.0 4.0
5 5 CBN 15.0 20.0
6 5 DSV 25.0 35.0
to:
ID MISSING_A MISSING_B 1T_A 1T_B 2T_A 2T_B CBN_A CBN_B DSV_A DSV_B
0 1 0.0 0.0 NaN NaN NaN NaN NaN NaN NaN NaN
1 2 NaN NaN 1.0 2.0 3.0 4.0 NaN NaN NaN NaN
3 3 0.0 0.0 NaN NaN NaN NaN NaN NaN NaN NaN
4 4 10.0 4.0 NaN NaN 10.0 4.0 NaN NaN NaN NaN
5 5 NaN NaN NaN NaN NaN NaN 15.0 20.0 25.0 35.0
For IDs with multiple types, multiple rows for A and B to merge into one row as shown above.
You are looking for a pivot, which will end up giving you a multi-index. You'll need to join those columns to get the suffix you are looking for.
df = df.pivot(index='ID',columns='TYPE', values=['A','B'])
df.columns = ['_'.join(reversed(col)).strip() for col in df.columns.values]
df.reset_index()
I have a pandas dataframe that summarises sales by calendar month & outputs something like:
Month level_0 UNIQUE_ID 102018 112018 12018 122017 122018 22018 32018 42018 52018 62018 72018 82018 92018
0 SOLD_QUANTITY 01 3692.0 5182.0 3223.0 1292.0 2466.0 2396.0 2242.0 2217.0 3590.0 2593.0 1665.0 3371.0 3069.0
1 SOLD_QUANTITY 011 3.0 6.0 NaN NaN 7.0 5.0 2.0 1.0 5.0 NaN 1.0 1.0 3.0
2 SOLD_QUANTITY 02 370.0 130.0 NaN NaN 200.0 NaN NaN 269.0 202.0 NaN 201.0 125.0 360.0
3 SOLD_QUANTITY 03 2.0 6.0 NaN NaN 2.0 1.0 NaN 6.0 11.0 9.0 2.0 3.0 5.0
4 SOLD_QUANTITY 08 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN 175.0 NaN NaN
I want to be able to programmatically re-arrange the column headers in ascending date order (eg starting 122017, 12018, 22018...). I need to do it in a way that is programmatic as every way the report runs, it will be a different list of months as it runs every month for last 365 days.
The index data type:
Index(['level_0', 'UNIQUE_ID', '102018', '112018', '12018', '122017', '122018',
'22018', '32018', '42018', '52018', '62018', '72018', '82018', '92018'],
dtype='object', name='Month')
Use set_index for only dates columns, convert them to datetimes and get order positions by argsort, then change ordering with iloc:
df = df.set_index(['level_0','UNIQUE_ID'])
df = df.iloc[:, pd.to_datetime(df.columns, format='%m%Y').argsort()].reset_index()
print (df)
level_0 UNIQUE_ID 122017 12018 22018 32018 42018 52018 \
0 SOLD_QUANTITY 1 1292.0 3223.0 2396.0 2242.0 2217.0 3590.0
1 SOLD_QUANTITY 11 NaN NaN 5.0 2.0 1.0 5.0
2 SOLD_QUANTITY 2 NaN NaN NaN NaN 269.0 202.0
3 SOLD_QUANTITY 3 NaN NaN 1.0 NaN 6.0 11.0
4 SOLD_QUANTITY 8 NaN NaN NaN NaN NaN NaN
62018 72018 82018 92018 102018 112018 122018
0 2593.0 1665.0 3371.0 3069.0 3692.0 5182.0 2466.0
1 NaN 1.0 1.0 3.0 3.0 6.0 7.0
2 NaN 201.0 125.0 360.0 370.0 130.0 200.0
3 9.0 2.0 3.0 5.0 2.0 6.0 2.0
4 NaN 175.0 NaN NaN NaN NaN NaN
Another idea is create month period index by DatetimeIndex.to_period, so is possible use sort_index:
df = df.set_index(['level_0','UNIQUE_ID'])
df.columns = pd.to_datetime(df.columns, format='%m%Y').to_period('m')
#alternative for convert to datetimes
#df.columns = pd.to_datetime(df.columns, format='%m%Y')
df = df.sort_index(axis=1).reset_index()
print (df)
level_0 UNIQUE_ID 2017-12 2018-01 2018-02 2018-03 2018-04 \
0 SOLD_QUANTITY 1 1292.0 3223.0 2396.0 2242.0 2217.0
1 SOLD_QUANTITY 11 NaN NaN 5.0 2.0 1.0
2 SOLD_QUANTITY 2 NaN NaN NaN NaN 269.0
3 SOLD_QUANTITY 3 NaN NaN 1.0 NaN 6.0
4 SOLD_QUANTITY 8 NaN NaN NaN NaN NaN
2018-05 2018-06 2018-07 2018-08 2018-09 2018-10 2018-11 2018-12
0 3590.0 2593.0 1665.0 3371.0 3069.0 3692.0 5182.0 2466.0
1 5.0 NaN 1.0 1.0 3.0 3.0 6.0 7.0
2 202.0 NaN 201.0 125.0 360.0 370.0 130.0 200.0
3 11.0 9.0 2.0 3.0 5.0 2.0 6.0 2.0
4 NaN NaN 175.0 NaN NaN NaN NaN NaN
I have a datetime indexed series like this:
2018-08-27 17:45:01 1
2018-08-27 16:01:12 1
2018-08-27 13:48:47 1
2018-08-26 22:26:40 2
2018-08-26 20:10:42 1
2018-08-26 18:20:32 1
2018-08-25 23:07:51 1
2018-08-25 01:46:08 1
2018-09-18 14:08:23 1
2018-09-17 19:38:38 1
2018-09-15 22:40:45 1
What is an elegant way to reformat this into a time indexed dataframe whose columns are dates? For example:
2018-10-24 2018-06-28 2018-10-23
15:16:41 1.0 NaN NaN
15:18:16 1.0 NaN NaN
15:21:42 1.0 NaN NaN
23:35:00 NaN NaN 1.0
23:53:13 NaN 1.0 NaN
Current approach:
time_date_dict = defaultdict(partial(defaultdict, int))
for i in series.iteritems():
datetime = i[0]
value = i[1]
time_date_dict[datetime.time()][datetime.date()] = value
time_date_df = pd.DataFrame.from_dict(time_date_dict, orient='index')
Use pivot:
df1 = pd.pivot(s.index.time, s.index.date, s)
#if want strings index and columns names
#df1 = pd.pivot(s.index.strftime('%H:%M:%S'), s.index.strftime('%Y-%m-%d'), s)
print (df1)
date 2018-08-25 2018-08-26 2018-08-27 2018-09-15 2018-09-17 \
date
01:46:08 1.0 NaN NaN NaN NaN
13:48:47 NaN NaN 1.0 NaN NaN
14:08:23 NaN NaN NaN NaN NaN
16:01:12 NaN NaN 1.0 NaN NaN
17:45:01 NaN NaN 1.0 NaN NaN
18:20:32 NaN 1.0 NaN NaN NaN
19:38:38 NaN NaN NaN NaN 1.0
20:10:42 NaN 1.0 NaN NaN NaN
22:26:40 NaN 2.0 NaN NaN NaN
22:40:45 NaN NaN NaN 1.0 NaN
23:07:51 1.0 NaN NaN NaN NaN
date 2018-09-18
date
01:46:08 NaN
13:48:47 NaN
14:08:23 1.0
16:01:12 NaN
17:45:01 NaN
18:20:32 NaN
19:38:38 NaN
20:10:42 NaN
22:26:40 NaN
22:40:45 NaN
23:07:51 NaN
I set up a new data frame SimMean:
columns = ['Tenor','5x16', '7x8', '2x16H']
index = range(0,12)
SimMean = pd.DataFrame(index=index, columns=columns)
SimMean
Tenor 5x16 7x8 2x16H
0 NaN NaN NaN NaN
1 NaN NaN NaN NaN
2 NaN NaN NaN NaN
3 NaN NaN NaN NaN
4 NaN NaN NaN NaN
5 NaN NaN NaN NaN
6 NaN NaN NaN NaN
7 NaN NaN NaN NaN
8 NaN NaN NaN NaN
9 NaN NaN NaN NaN
10 NaN NaN NaN NaN
11 NaN NaN NaN NaN
I have another data frame FwdDf:
FwdDf
Tenor 5x16 7x8 2x16H
0 2017-01-01 50.94 34.36 43.64
1 2017-02-01 50.90 32.60 42.68
2 2017-03-01 42.66 26.26 37.26
3 2017-04-01 37.08 22.65 32.46
4 2017-05-01 42.21 20.94 33.28
5 2017-06-01 39.30 22.05 32.29
6 2017-07-01 50.90 21.80 38.51
7 2017-08-01 42.77 23.64 35.07
8 2017-09-01 37.45 19.61 32.68
9 2017-10-01 37.55 21.75 32.10
10 2017-11-01 35.61 22.73 32.90
11 2017-12-01 40.16 29.79 37.49
12 2018-01-01 53.45 36.09 47.61
13 2018-02-01 52.89 35.74 45.00
14 2018-03-01 44.67 27.79 38.62
15 2018-04-01 38.48 24.21 34.43
16 2018-05-01 43.87 22.17 34.69
17 2018-06-01 40.24 22.85 34.31
18 2018-07-01 49.98 23.58 39.96
19 2018-08-01 45.57 24.76 37.23
20 2018-09-01 38.90 21.74 34.22
21 2018-10-01 39.75 23.36 35.20
22 2018-11-01 38.04 24.20 34.62
23 2018-12-01 42.68 31.03 40.00
now I need to assign the 'Tenor' data from row 12 to row 23 in FwdDf to the new data frame SimMean.
I used
SimMean.loc[0:11,'Tenor'] = FwdDf.loc [12:23,'Tenor']
but it didn't work:
SimMean
Tenor 5x16 7x8 2x16H
0 None NaN NaN NaN
1 None NaN NaN NaN
2 None NaN NaN NaN
3 None NaN NaN NaN
4 None NaN NaN NaN
5 None NaN NaN NaN
6 None NaN NaN NaN
7 None NaN NaN NaN
8 None NaN NaN NaN
9 None NaN NaN NaN
10 None NaN NaN NaN
11 None NaN NaN NaN
I'm new to python. I would appreciate your help. Thanks
call .values so there are no index alignment issues:
In [35]:
SimMean.loc[0:11,'Tenor'] = FwdDf.loc[12:23,'Tenor'].values
SimMean
Out[35]:
Tenor 5x16 7x8 2x16H
0 2018-01-01 NaN NaN NaN
1 2018-02-01 NaN NaN NaN
2 2018-03-01 NaN NaN NaN
3 2018-04-01 NaN NaN NaN
4 2018-05-01 NaN NaN NaN
5 2018-06-01 NaN NaN NaN
6 2018-07-01 NaN NaN NaN
7 2018-08-01 NaN NaN NaN
8 2018-09-01 NaN NaN NaN
9 2018-10-01 NaN NaN NaN
10 2018-11-01 NaN NaN NaN
11 2018-12-01 NaN NaN NaN
EDIT
As your column is actually datetime then you need to convert the type again:
In [46]:
SimMean['Tenor'] = pd.to_datetime(SimMean['Tenor'])
SimMean
Out[46]:
Tenor 5x16 7x8 2x16H
0 2018-01-01 NaN NaN NaN
1 2018-02-01 NaN NaN NaN
2 2018-03-01 NaN NaN NaN
3 2018-04-01 NaN NaN NaN
4 2018-05-01 NaN NaN NaN
5 2018-06-01 NaN NaN NaN
6 2018-07-01 NaN NaN NaN
7 2018-08-01 NaN NaN NaN
8 2018-09-01 NaN NaN NaN
9 2018-10-01 NaN NaN NaN
10 2018-11-01 NaN NaN NaN
11 2018-12-01 NaN NaN NaN