当前位置: 首页 > 知识库问答 >
问题:

熊猫:如何将一列中的文本拆分为多行?

潘泰
2023-03-14

我正在处理一个大的csv文件,下一列的最后一列有一个文本字符串,我想用一个特定的分隔符来分割。我想知道是否有一种简单的方法可以使用pandas或python来实现这一点?

CustNum  CustomerName     ItemQty  Item   Seatblocks                 ItemExt
32363    McCartney, Paul      3     F04    2:218:10:4,6                   60
31316    Lennon, John        25     F01    1:13:36:1,12 1:13:37:1,13     300

我想按(' ')空格分割,然后按Seatblock列中的冒号(':')分割,但是每个单元格将导致不同数量的列。我有一个重新排列列的函数,所以Seatblock列在工作表的末尾,但是我不确定从那里做什么。我可以在excel中使用内置的文本到列函数和一个快速宏来完成,但是我的数据集有太多的记录需要excel来处理。

最后,我想录制约翰·列侬(John Lennon)的唱片并创建多行,将每组座位的信息放在单独的行中。

共有3个答案

夔高寒
2023-03-14
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_indexrename

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仅使用参数expand=True工作str.split,返回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
王扬
2023-03-14

与丹不同,我认为他的回答相当优雅。但不幸的是,它也非常低效。因此,既然问题提到了“一个大的csv文件”,让我建议尝试使用shell Dan的解决方案:

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倍左右,因为它甚至避免了对100000个列表进行实例验证。是的,它确实有点难看。。。

编辑:这个答案建议如何使用“to_list()”并避免需要λ。结果是类似于

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()"
彭宏义
2023-03-14

这将座椅块按空间分开,并给每个座椅块自己的行。

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

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

 类似资料:
  • 我的问题是如何将一列拆分为多个列。我不知道为什么 不起作用。 例如,我想将“df_test”更改为“df_test2”。我看到了很多使用熊猫模块的例子。还有别的办法吗?提前感谢您。 df_test2

  • 我有一个这样的专栏: 现在我想在dot在列中如下所示:

  • 我有一个熊猫的数据框,有一列是向量: 我想把它拆分成这样的元素: df2=pd.DataFrame({'ID':[1,2],'A':[1,4],'B':[2,5],'C':[3,6]}) 我试过但是没有运气.任何帮助将不胜感激。

  • 在下面的例子中,我有电影的数据: 我想将标题列值拆分为2个新列,即其中一个新列(“电影标题”)将采用=玩具故事作为行值,另一个新列(“年份”)将采用= 1995作为行值。 如何对整个数据帧执行此操作?

  • 我的主要问题是列表的长度不一样。但是所有列表只包含最多相同的3个值:'a'、'b'和'c'。它们总是以相同的顺序出现('a'第一,'b'第二,'c'第三)。 下面的代码用来工作并返回我想要的东西(df2)。 我上周刚刚运行了这个代码,它运行得很好。但是现在我的代码坏了,我从第[4]行得到了这个错误: 数据以这种格式从数据库导入。对这个问题有什么帮助或想法吗?有办法转换Unicode吗?

  • 我有一个数据帧: 如何拆分该列,使每个值都在自己的列中? 我找到的唯一答案是关于将一列拆分成两列。如何将一列拆分成两列?