Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/337.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在数据帧中将单元格拆分为多行_Python_Pandas_Dataframe - Fatal编程技术网

Python 在数据帧中将单元格拆分为多行

Python 在数据帧中将单元格拆分为多行,python,pandas,dataframe,Python,Pandas,Dataframe,我有一个包含订单数据的数据框,每个订单都有多个以逗号分隔的字符串[package&package\u code]列存储的包 我想分割包数据,并为每个包创建一行,包括其订单详细信息 以下是一个示例输入数据帧: import pandas as pd df = 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
&
package\u code
]列存储的包

我想分割包数据,并为每个包创建一行,包括其订单详细信息

以下是一个示例输入数据帧:

import pandas as pd
df = 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"]})

这就是我试图实现的输出:

我怎样才能对熊猫做到这一点呢?

pandas>=0.25 假设所有可拆分列具有相同数量的逗号分隔项,则可以按逗号拆分,然后在每列上使用:

(df.set_index(['order_id', 'order_date'])
   .apply(lambda x: x.str.split(',').explode())
   .reset_index())                                                   

   order_id order_date package package_code
0         1  20/5/2018      p1         #111
1         1  20/5/2018      p2         #222
2         1  20/5/2018      p3         #333
3         3  22/5/2018      p4         #444
4         7  23/5/2018      p5         #555
5         7  23/5/2018      p6         #666
详细信息

将不被触摸的列设置为索引

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

                      package    package_code
order_id order_date                          
1        20/5/2018   p1,p2,p3  #111,#222,#333
3        22/5/2018         p4            #444
7        23/5/2018      p5,p6       #555,#666
下一步是一个分为两步的过程:使用逗号拆分以获得一列列表,然后调用
explode
将列表值分解为各自的行

_.apply(lambda x: x.str.split(',').explode())

                    package package_code
order_id order_date                     
1        20/5/2018       p1         #111
         20/5/2018       p2         #222
         20/5/2018       p3         #333
3        22/5/2018       p4         #444
7        23/5/2018       p5         #555
         23/5/2018       p6         #666
最后,重置索引

_.reset_index()

   order_id order_date package package_code
0         1  20/5/2018      p1         #111
1         1  20/5/2018      p2         #222
2         1  20/5/2018      p3         #333
3         3  22/5/2018      p4         #444
4         7  23/5/2018      p5         #555
5         7  23/5/2018      p6         #666
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


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

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
接近cold的方法:-)


看看今天的熊猫0.25版:


鉴于
explode
只影响列表列,一个简单的解决方案是:

# Convert columns of interest to list columns
d["package"]      = d["package"].str.split(",")
d["package_code"] = d["package_code"].str.split(",")

# Explode the entire data frame
d = d.apply( pandas.Series.explode )
优势

  • 避免了必须将核心数据移动到索引以“防止其妨碍”,因此当数据包含重复数据时,不会因“重复索引”错误而失败
缺点

  • 仅当数据中没有列表列时才有效(尽管几乎总是这样)

这有用吗@coldspeed是的,我将在我的脑海中再次强调它(应用是不好的!:-()如果
apply(pd.Series)
是不好的,是不是
stack
更差?我看到它经常表现得比简单的迭代差!@jpp是的,这是对温的一般建议(他明白了)因为他使用它的次数比他应该使用的多了一点,而且你会期望一个拥有金徽章的60k用户想要尽可能地宣传好的实践;-)当然堆栈很糟糕,但是它的灵活性是有用的。你能补充一下吗details@pyd关于这一点,您具体想知道什么?使用
-2
解压和使用
-1
@AdarshRavi重置索引时会发生什么情况?您可以这样做:
保留列=列表(设置(df.columns)-set([重塑列])
I更新的熊猫(版本1.0.3)最新的表单似乎不再有效:
ValueError:无法处理非唯一的多索引。如果有两列需要扩展并且具有不同的镜头,该怎么办?@Moj,这个问题还没有很好地定义。例如,不能使用1对1映射将3个值与5个值对齐。我建议你问一个新问题,如果你的问题没有在其他地方得到回答,那么你可以精确地指定你想要的输出。这很好。很高兴知道(a)Pandas是如何在内部实现此功能的,(b)此解决方案在性能方面与其他解决方案相比如何。今年只能分解一列way@cs95不,可以通过如下方式在多个列上分解:
df=pd.DataFrame([{'var1':'a,b,c','var3':'x1,x2,x3','var2':1},{'var1':'d,e,f','var3':'x1,x2,x4','var2':2}])df.assign(var1=df.var1.str.split(','),var3=df.var3.str.split(',')).explode('var1')。explode('var3')。reset_index(drop=True)
结果不正确,每列单独分解,而不是相互串联,结果中产生的行数超过预期。我不明白,你能举一个所需数据和结果的示例吗?
_.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
_.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)

                      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(-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
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
df.set_index(['order_date','order_id']).apply(lambda x : x.str.split(',')).stack().apply(pd.Series).stack().unstack(level=2).reset_index(level=[0,1])
Out[538]: 
  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
0  22/5/2018         3      p4         #444
0  23/5/2018         7      p5         #555
1  23/5/2018         7      p6         #666
df = pd.DataFrame([{'var1': 'a,b,c', 'var2': 1}, {'var1': 'd,e,f', 'var2': 2}])
df.assign(var1=df.var1.str.split(',')).explode('var1').reset_index(drop=True)
# Convert columns of interest to list columns
d["package"]      = d["package"].str.split(",")
d["package_code"] = d["package_code"].str.split(",")

# Explode the entire data frame
d = d.apply( pandas.Series.explode )