根据日期列将数据框重塑为多列

Reshape dataframe into several columns based on date column

我想根据日期列重新排列下面的示例数据框 (df.csv)。每行代表一个小时的数据,例如2002-01-01和2002-01-02这两个日期,分别有5行,每行代表1小时。

date,symbol
2002-01-01,A
2002-01-01,A
2002-01-01,A
2002-01-01,B
2002-01-01,A
2002-01-02,B
2002-01-02,B
2002-01-02,A
2002-01-02,A
2002-01-02,A

我的预期输出如下。

date,hour1, hour2, hour3, hour4, hour5
2002-01-01,A,A,A,B,A
2002-01-02,B,B,A,A,A

我已经按照此处的说明尝试了以下方法:https://pandas.pydata.org/docs/user_guide/reshaping.html,但在我的情况下它不起作用,因为符号列包含重复项。

import pandas as pd
import numpy as np

df = pd.read_csv('df.csv')

pivoted = df.pivot(index="date", columns="symbol")
print(pivoted)

数据没有时间戳,只有日期。但是,同一日期的每一行代表一个小时间隔,例如输出也可以表示如下:

date,01:00, 02:00, 03:00, 04:00, 05:00
2002-01-01,A,A,A,B,A
2002-01-02,B,B,A,A,A

其中 hour1 代表 01:00,hour2 代表 02:00...等

我可以为您提供一个方法,我想这不是最优雅的方法,因为我必须重命名索引和列,但它可以完成工作。

new_cols = ['01:00', '02:00', '03:00', '04:00', '05:00']
df1 = df.loc[df['date']=='2002-01-01', :].T.drop('date').set_axis(new_cols, axis=1).set_axis(['2002-01-01'])
df2 = df.loc[df['date']=='2002-01-02', :].T.drop('date').set_axis(new_cols, axis=1).set_axis(['2002-01-02'])

result = pd.concat([df1,df2])

print(result)

Output:

                01:00   02:00   03:00   04:00   05:00
2002-01-01      A       A       A       B       A
2002-01-02      B       B       A       A       A

您采用了正确的 pivot 方法,但您缺少一列 'time',所以让我们将日期时间拆分为日期和时间:

s = pd.to_datetime(df['date'])
df['date'] = s.dt.date
df['time'] = s.dt.time
df2 = df.pivot(index='date', columns='time', values='symbol')

输出:

time       01:00:00 02:00:00 03:00:00 04:00:00 05:00:00
date                                                   
2002-01-01        A        A        A        B        A
2002-01-02        B        B        A        A        A

或者有 HH:MM 时间,使用 df['time'] = s.dt.strftime('%H:%M')

使用的输入:

date,symbol
2002-01-01 01:00,A
2002-01-01 02:00,A
2002-01-01 03:00,A
2002-01-01 04:00,B
2002-01-01 05:00,A
2002-01-02 01:00,B
2002-01-02 02:00,B
2002-01-02 03:00,A
2002-01-02 04:00,A
2002-01-02 05:00,A

输入的不是时间!

如果你真的没有时间输入日期并且需要'invent'增加日期,你可以使用groupby.cumcount:

df['time'] = pd.to_datetime(df.groupby('date').cumcount(), format='%H').dt.strftime('%H:%M')
df2 = df.pivot(index='date', columns='time', values='symbol')

输出:

time       01:00 02:00 03:00 04:00 05:00
date                                    
2002-01-01     A     A     A     B     A
2002-01-02     B     B     A     A     A

对于一个小时的每个条目:

k = df.groupby("date").cumcount().add(1).astype(str).radd("hour")
out = df.pivot_table('symbol','date',k,aggfunc=min)
print(out)

           hour1 hour2 hour3 hour4 hour5
date                                    
2002-01-01     A     A     A     B     A
2002-01-02     B     B     A     A     A