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

熊猫:如何将列中的文本分割成多行?

熊猫:如何将列中的文本分割成多行?

慕娘9325324 2019-07-04 13:09:20
熊猫:如何将列中的文本分割成多行?我正在处理一个大型CSV文件,最后一列的旁边有一个文本字符串,我想用一个特定的分隔符来分割。我想知道是否有一种使用熊猫或蟒蛇的简单方法?CustNum  CustomerName     ItemQty  Item   Seatblocks                 ItemExt32363    McCartney, Paul       3     F04    2:218:10:4,6                   6031316    Lennon, John        25     F01      1:13:36:1,12 1:13:37:1,13     300我想分道扬镳(' ')然后是结肠(':')在Seatblocks列,但每个单元格将导致不同的列数。我有一个函数来重新排列,所以Seatblocks列在纸的末尾,但我不知道该怎么做。我可以在excel中使用内置的text-to-columns函数和快速宏,但是我的数据集有太多的记录需要Excel处理。最后,我想记录下约翰列侬的记录,并创建多行,每一组座位的信息都在一条单独的线路上。
查看完整描述

3 回答

?
明月笑刀无情

TA贡献1828条经验 获得超4个赞


这将SeatBlock按空间划分,并给出各自的行。


In [43]: df

Out[43]: 

   CustNum     CustomerName  ItemQty Item                 Seatblocks  ItemExt

0    32363  McCartney, Paul        3  F04               2:218:10:4,6       60

1    31316     Lennon, John       25  F01  1:13:36:1,12 1:13:37:1,13      300


In [44]: s = df['Seatblocks'].str.split(' ').apply(Series, 1).stack()


In [45]: s.index = s.index.droplevel(-1) # to line up with df's index


In [46]: s.name = 'Seatblocks' # needs a name to join


In [47]: s

Out[47]: 

0    2:218:10:4,6

1    1:13:36:1,12

1    1:13:37:1,13

Name: Seatblocks, dtype: object


In [48]: del df['Seatblocks']


In [49]: df.join(s)

Out[49]: 

   CustNum     CustomerName  ItemQty Item  ItemExt    Seatblocks

0    32363  McCartney, Paul        3  F04       60  2:218:10:4,6

1    31316     Lennon, John       25  F01      300  1:13:36:1,12

1    31316     Lennon, John       25  F01      300  1:13:37:1,13

或者,在它自己的列中给每个冒号分隔的字符串:


In [50]: df.join(s.apply(lambda x: Series(x.split(':'))))

Out[50]: 

   CustNum     CustomerName  ItemQty Item  ItemExt  0    1   2     3

0    32363  McCartney, Paul        3  F04       60  2  218  10   4,6

1    31316     Lennon, John       25  F01      300  1   13  36  1,12

1    31316     Lennon, John       25  F01      300  1   13  37  1,13

这有点难看,但也许有人会提出一个更漂亮的解决方案。


查看完整回答
反对 回复 2019-07-04
?
神不在的星期二

TA贡献1963条经验 获得超6个赞

不同于丹,我认为他的回答很优雅.但不幸的是,这也是非常低效的。所以,既然刚才提到的问题“大CSV文件”,让我建议试试壳牌丹的解决方案:

time python -c "import pandas as pd;
df = pd.DataFrame(['a b c']*100000, columns=['col']);
print df['col'].apply(lambda x : pd.Series(x.split(' '))).head()"

..与这一备选方案相比:

time python -c "import pandas as pd;
from scipy import array, concatenate;
df = pd.DataFrame(['a b c']*100000, columns=['col']);
print pd.DataFrame(concatenate(df['col'].apply( lambda x : [x.split(' ')]))).head()"

..这是:

time python -c "import pandas as pd;
df = pd.DataFrame(['a b c']*100000, columns=['col']);
print pd.DataFrame(dict(zip(range(3), [df['col'].apply(lambda x : x.split(' ')[i]) for i in range(3)]))).head()"

第二个简单地避免分配100000系列,这足以使它大约快10倍。但是第三种解决方案(具有讽刺意味的是,它浪费了很多对str.split()的调用)(每行每列调用一次,因此比其他两种解决方案多三倍)。40次比第一个更快,因为它甚至避免了10万个列表的实例。是的,确实有点丑.

编辑: 这个答案建议如何使用“to_list()”并避免使用lambda。结果就像

time python -c "import pandas as pd;
df = pd.DataFrame(['a b c']*100000, columns=['col']);
print pd.DataFrame(df.col.str.split().tolist()).head()"

这甚至比第三种解决方案更有效,当然也更优雅。

编辑:更简单

time python -c "import pandas as pd;
df = pd.DataFrame(['a b c']*100000, columns=['col']);
print pd.DataFrame(list(df.col.str.split())).head()"

也起作用,而且是差不多了很有效率。

编辑: 更简单!并处理NAN(但效率较低):

time python -c "import pandas as pd;
df = pd.DataFrame(['a b c']*100000, columns=['col']);
print df.col.str.split(expand=True).head()"


查看完整回答
反对 回复 2019-07-04
?
繁星点点滴滴

TA贡献1803条经验 获得超3个赞


import pandas as pd

import numpy as np


df = pd.DataFrame({'ItemQty': {0: 3, 1: 25}, 

                   'Seatblocks': {0: '2:218:10:4,6', 1: '1:13:36:1,12 1:13:37:1,13'}, 

                   'ItemExt': {0: 60, 1: 300}, 

                   'CustomerName': {0: 'McCartney, Paul', 1: 'Lennon, John'}, 

                   'CustNum': {0: 32363, 1: 31316}, 

                   'Item': {0: 'F04', 1: 'F01'}}, 

                    columns=['CustNum','CustomerName','ItemQty','Item','Seatblocks','ItemExt'])


print (df)

   CustNum     CustomerName  ItemQty Item                 Seatblocks  ItemExt

0    32363  McCartney, Paul        3  F04               2:218:10:4,6       60

1    31316     Lennon, John       25  F01  1:13:36:1,12 1:13:37:1,13      300

另一种类似的链接解决方案是使用reset_index和rename:


print (df.drop('Seatblocks', axis=1)

             .join

             (

             df.Seatblocks

             .str

             .split(expand=True)

             .stack()

             .reset_index(drop=True, level=1)

             .rename('Seatblocks')           

             ))


   CustNum     CustomerName  ItemQty Item  ItemExt    Seatblocks

0    32363  McCartney, Paul        3  F04       60  2:218:10:4,6

1    31316     Lennon, John       25  F01      300  1:13:36:1,12

1    31316     Lennon, John       25  F01      300  1:13:37:1,13

如果在列中是不 NaN值,最快的解决方案是使用list理解力DataFrame构造者:


df = pd.DataFrame(['a b c']*100000, columns=['col'])


In [141]: %timeit (pd.DataFrame(dict(zip(range(3), [df['col'].apply(lambda x : x.split(' ')[i]) for i in range(3)]))))

1 loop, best of 3: 211 ms per loop


In [142]: %timeit (pd.DataFrame(df.col.str.split().tolist()))

10 loops, best of 3: 87.8 ms per loop


In [143]: %timeit (pd.DataFrame(list(df.col.str.split())))

10 loops, best of 3: 86.1 ms per loop


In [144]: %timeit (df.col.str.split(expand=True))

10 loops, best of 3: 156 ms per loop


In [145]: %timeit (pd.DataFrame([ x.split() for x in df['col'].tolist()]))

10 loops, best of 3: 54.1 ms per loop

但是如果列包含NaN只起作用str.split带参数expand=True哪一回DataFrame (文献资料),它解释了为什么它更慢:


df = pd.DataFrame(['a b c']*10, columns=['col'])

df.loc[0] = np.nan

print (df.head())

     col

0    NaN

1  a b c

2  a b c

3  a b c

4  a b c


print (df.col.str.split(expand=True))

     0     1     2

0  NaN  None  None

1    a     b     c

2    a     b     c

3    a     b     c

4    a     b     c

5    a     b     c

6    a     b     c

7    a     b     c

8    a     b     c

9    a     b     c


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

添加回答

举报

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