为了账号安全,请及时绑定邮箱和手机立即绑定

在pandas数据框中将单元格拆分为多行

在pandas数据框中将单元格拆分为多行

慕尼黑8549860 2019-10-11 10:33:07
我有一个包含订单数据的数据框,每个订单都有多个存储为逗号分隔的字符串[ package&package_code]列的包我想拆分包裹数据并为每个包裹创建一行,包括其订单明细这是一个示例输入数据框:import pandas as pddf = pd.DataFrame({"order_id":[1,3,7],"order_date":["20/5/2018","22/5/2018","23/5/2018"], "package":["p1,p2,p3","p4","p5,p6"],"package_code":["#111,#222,#333","#444","#555,#666"]})这就是我想要实现的输出结果: 我该如何用熊猫呢?
查看完整描述

3 回答

?
沧海一幻觉

TA贡献1824条经验 获得超5个赞

这是使用numpy.repeat和的一种方法itertools.chain。从概念上讲,这正是您想要做的:重复某些值,链接其他值。建议用于少量的列,否则stack基于方法的方法可能会更好。


import numpy as np

from itertools import chain


# return list from series of comma-separated strings

def chainer(s):

    return list(chain.from_iterable(s.str.split(',')))


# calculate lengths of splits

lens = df['package'].str.split(',').map(len)


# create new dataframe, repeating or chaining as appropriate

res = pd.DataFrame({'order_id': np.repeat(df['order_id'], lens),

                    'order_date': np.repeat(df['order_date'], lens),

                    'package': chainer(df['package']),

                    'package_code': chainer(df['package_code'])})


print(res)


   order_id order_date package package_code

0         1  20/5/2018      p1         #111

0         1  20/5/2018      p2         #222

0         1  20/5/2018      p3         #333

1         3  22/5/2018      p4         #444

2         7  23/5/2018      p5         #555

2         7  23/5/2018      p6         #666


查看完整回答
反对 回复 2019-10-11
?
江户川乱折腾

TA贡献1851条经验 获得超5个赞

这适用于任何数量的列,例如这样。本质是带有的一点堆叠-堆叠功能str.split。


(df.set_index(['order_date', 'order_id'])

   .stack()

   .str.split(',', expand=True)

   .stack()

   .unstack(-2)

   .reset_index(-1, drop=True)

   .reset_index()

)


  order_date  order_id package package_code

0  20/5/2018         1      p1         #111

1  20/5/2018         1      p2         #222

2  20/5/2018         1      p3         #333

3  22/5/2018         3      p4         #444

4  23/5/2018         7      p5         #555

5  23/5/2018         7      p6         #666

还有另一个涉及的性能替代方案chain,但是您需要显式地链接并重复每列(很多列都有问题)。由于没有单一答案,因此请选择最适合您问题描述的内容。


细节


首先,将不被触及的列设置为索引。


df.set_index(['order_date', 'order_id'])


                      package    package_code

order_date order_id                          

20/5/2018  1         p1,p2,p3  #111,#222,#333

22/5/2018  3               p4            #444

23/5/2018  7            p5,p6       #555,#666

接下来,stack行。


_.stack()


order_date  order_id              

20/5/2018   1         package               p1,p2,p3

                      package_code    #111,#222,#333

22/5/2018   3         package                     p4

                      package_code              #444

23/5/2018   7         package                  p5,p6

                      package_code         #555,#666

dtype: object

我们现在有一系列。因此请str.split使用逗号。


_.str.split(',', expand=True)


                                     0     1     2

order_date order_id                               

20/5/2018  1        package         p1    p2    p3

                    package_code  #111  #222  #333

22/5/2018  3        package         p4  None  None

                    package_code  #444  None  None

23/5/2018  7        package         p5    p6  None

                    package_code  #555  #666  None

我们需要摆脱NULL值,因此stack再次调用。


_.stack()


order_date  order_id                 

20/5/2018   1         package       0      p1

                                    1      p2

                                    2      p3

                      package_code  0    #111

                                    1    #222

                                    2    #333

22/5/2018   3         package       0      p4

                      package_code  0    #444

23/5/2018   7         package       0      p5

                                    1      p6

                      package_code  0    #555

                                    1    #666

dtype: object

我们快到了。现在我们希望索引的倒数第二层成为我们的列,因此使用unstack(-2)(unstack在倒数第二层)上的堆栈


_.unstack(-2)


                      package package_code

order_date order_id                       

20/5/2018  1        0      p1         #111

                    1      p2         #222

                    2      p3         #333

22/5/2018  3        0      p4         #444

23/5/2018  7        0      p5         #555

                    1      p6         #666

使用reset_index以下命令摆脱多余的最后一级:


_.reset_index(-1, drop=True)


                    package package_code

order_date order_id                     

20/5/2018  1             p1         #111

           1             p2         #222

           1             p3         #333

22/5/2018  3             p4         #444

23/5/2018  7             p5         #555

           7             p6         #666

最后,


_.reset_index()


  order_date  order_id package package_code

0  20/5/2018         1      p1         #111

1  20/5/2018         1      p2         #222

2  20/5/2018         1      p3         #333

3  22/5/2018         3      p4         #444

4  23/5/2018         7      p5         #555

5  23/5/2018         7      p6         #666


查看完整回答
反对 回复 2019-10-11
  • 3 回答
  • 0 关注
  • 1857 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信