我有一个如下所示的熊猫数据框:
id val date period1 period2 period3
1 4 05/03 1 2 3
2 6 06/03 4 5 6
3 2 07/03 7 8 9
4 9 08/03 5 7 1
我想根据以下日期和时间段将其从宽转换为长:
id val date period data
1 4 05/03 06/03 1
07/03 2
08/03 3
2 6 06/03 07/03 4
08/03 5
09/03 6
3 2 07/03 08/03 7
09/03 8
10/03 9
4 9 08/03 09/03 5
10/03 7
11/03 1
这是period的值,将是date + 1month(年份也可能更改)的值,依此类推,其对应的值出现在data列中,而其余的数据框则保持不变。
我该如何实现?
答案 0 :(得分:2)
首先用DataFrame.set_index
用DataFrame.stack
重塑值。
然后将date
列转换为Series.dt.to_period
的日期时间和月份,以GroupBy.cumcount
的方式每组添加计数器,并以Series.dt.strftime
的方式更改格式:
df = (df.set_index(['id','val','date'])
.rename_axis('period', axis=1)
.stack()
.reset_index(name='data'))
s = pd.to_datetime(df['date'], format='%m/%y').dt.to_period('m')
df['period'] = df.groupby(['id','val','date']).cumcount().add(s + 1).dt.strftime('%m/%y')
print (df)
id val date period data
0 1 4 05/03 06/03 1
1 1 4 05/03 07/03 2
2 1 4 05/03 08/03 3
3 2 6 06/03 07/03 4
4 2 6 06/03 08/03 5
5 2 6 06/03 09/03 6
6 3 2 07/03 08/03 7
7 3 2 07/03 09/03 8
8 3 2 07/03 10/03 9
9 4 9 08/03 09/03 5
10 4 9 08/03 10/03 7
11 4 9 08/03 11/03 1
如果最后3列需要空值,则最后一次-DataFrame.duplicated
是可以的,但是混合值-带字符串的数字,因此数字函数应该失败:
df.loc[df.duplicated(['id','val','date']), ['id','val','date']] = ''
print (df)
id val date period data
0 1 4 05/03 06/03 1
1 07/03 2
2 08/03 3
3 2 6 06/03 07/03 4
4 08/03 5
5 09/03 6
6 3 2 07/03 08/03 7
7 09/03 8
8 10/03 9
9 4 9 08/03 09/03 5
10 10/03 7
11 11/03 1
答案 1 :(得分:1)
使用wide_to_long
df1 = (pd.wide_to_long(df, stubnames='period', j='p', i=['id', 'val', 'date'])
.rename(columns={'period': 'data'}).reset_index())
df1['p'] = ((pd.to_datetime(df1.date, format='%m/%y').dt.to_period('M')
+ df1.p).dt.strftime('%m/%y'))
df1.rename(columns={'p': 'period'})
Out[193]:
id val date period data
0 1 4 05/03 06/03 1
1 1 4 05/03 07/03 2
2 1 4 05/03 08/03 3
3 2 6 06/03 07/03 4
4 2 6 06/03 08/03 5
5 2 6 06/03 09/03 6
6 3 2 07/03 08/03 7
7 3 2 07/03 09/03 8
8 3 2 07/03 10/03 9
9 4 9 08/03 09/03 5
10 4 9 08/03 10/03 7
11 4 9 08/03 11/03 1