如何 dcast pandas 数据框并将行转换为列
Posted
技术标签:
【中文标题】如何 dcast pandas 数据框并将行转换为列【英文标题】:how to dcast pandas dataframe and convert rows to columns 【发布时间】:2018-12-11 08:02:59 【问题描述】:我有以下熊猫数据框
df1
code prod rsp date_from date_to time_from time_to
123 MS 75 2018-01-01 2018-01-02 06:00 05:59
123 HS 65 2018-01-01 2018-01-02 06:00 05:59
123 MS 76 2018-01-01 2018-01-02 10:00 05:59
123 MS 76 2018-01-01 2018-01-02 11:00 05:59
123 MS 73 2018-01-02 2018-01-03 06:00 05:59
123 HS 64 2018-01-02 2018-01-03 06:00 05:59
123 MS 73 2018-01-02 2018-01-03 10:00 05:59
我想要的数据框是
code prod rsp_1 date_from date_to time_from_1 time_to_1 rsp_2 time_from_2 time_to_2
123 MS 75 2018-01-01 2018-01-02 06:00 05:59 76 10:00 05:59
123 HS 65 2018-01-01 2018-01-02 06:00 05:59 - - - - -
123 MS 73 2018-01-02 2018-01-03 06:00 05:59 - - - - -
123 HS 64 2018-01-02 2018-01-03 06:00 05:59 - - -
我在 python 中做以下操作
L = list(map(tuple,price[['code','prod','date_from']].values))
s = pd.Series(L, index=price.index)
s = s.ne(s.shift()).cumsum()
g = s.groupby(s).cumcount()
df1 = (price.set_index(['code','prod','date_from', s,g])
.unstack()
.sort_index(level=1, axis=1)
.reset_index(level=2, drop=True))
df1.columns = [f'i_j+1' for i, j in df1.columns]
df1 = df1.reset_index()
我希望将独特的价格 rsp
放入列中。例如,在 df1
中,对于产品 MS
和 date_from
2018-01-01,rsp
76 有两个重复条目,因此我们将只考虑第一个条目。所以对于 1 个产品,我们将只有一个日期和相应的价格变化历史。
【问题讨论】:
您能否解释一下 rsp_2 与 rsp_1 相关的所需逻辑? rsp_2 仅在同一天同一产品有多个价格变化且不同 rsp 的情况下才会出现。 【参考方案1】:使用drop_duplicates
然后似乎应该简化解决方案:
#by one column
price = price.drop_duplicates('rsp')
#if necessary by multiple columns
#cols = ['code','prod','date_from', 'date_to', 'rsp']
#price = price.drop_duplicates(subset=cols)
g = price.groupby(['code','prod','date_from', 'date_to']).cumcount()
df1 = (price.set_index(['code','prod','date_from','date_to', g])
.unstack()
.sort_index(level=1, axis=1))
df1.columns = [f'i_j+1' for i, j in df1.columns]
df1 = df1.reset_index()
print (df1)
code prod date_from date_to rsp_1 time_from_1 time_to_1 rsp_2 \
0 123 HS 2018-01-01 2018-01-02 65.0 06:00 05:59 NaN
1 123 HS 2018-01-02 2018-01-03 64.0 06:00 05:59 NaN
2 123 MS 2018-01-01 2018-01-02 75.0 06:00 05:59 76.0
3 123 MS 2018-01-02 2018-01-03 73.0 06:00 05:59 NaN
time_from_2 time_to_2
0 NaN NaN
1 NaN NaN
2 10:00 05:59
3 NaN NaN
【讨论】:
似乎对于第一行,drop_duplicate by code, prod, date_from, rsp 是必需的(即 df.drop_duplicates(subset=['code', 'prod','date_from','rsp' ],保持=假)) @Kryesec - 谢谢,已添加到解决方案中。 @jezrael 我们也可以在解决方案中添加date_from
吗?
@Neil - 你认为按所有 time_to_1, time_to_2, ...
列排序吗?
@Neil - 我的第一个想法是使用price = price.drop_duplicates('rsp').sort_values('time_from')
,它处理样本数据。但也许您需要按真实数据中的多列排序 - price = price.drop_duplicates('rsp').sort_values(['code','prod','date_from', 'date_to', 'time_from'])
。问题应该是如果按多列排序,它首先按 1. 列排序,然后按 2....所以最后一次排序可能是按最后一列,但不能按 1.、2. 列排序...所以最好的测试它与真实数据。以上是关于如何 dcast pandas 数据框并将行转换为列的主要内容,如果未能解决你的问题,请参考以下文章