如何 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 中,对于产品 MSdate_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 数据框并将行转换为列的主要内容,如果未能解决你的问题,请参考以下文章

如何按(月+年)转换为 Pandas 数据框进行分组?

如何将 pandas 数据框列转换为本机 python 数据类型?

如何填充列表中的值并将其转换为数据框?

将 pandas 嵌套的 JSON 结构转换为数据框

将 Pandas 数据框从基于行转换为列

pandas 数据框的颜色行并转换为 HTML 表