将 pandas 中的一个单元格拆分为多行

Posted

技术标签:

【中文标题】将 pandas 中的一个单元格拆分为多行【英文标题】:Splitting a cell in pandas into multiple rows 【发布时间】:2021-06-26 03:40:56 【问题描述】:

解释这个问题有点棘手。 我想将包含多个用逗号分隔的字符串值的单元格拆分为不同的行。下面的 df 是一个小示例,但实际数据集最多包含 15 列和 15 行,每个单元格中有 5 到 6 个非唯一字符串值,我需要将它们分成不同的行。

我们如何将原始df拆分为转换后的df

原始df

import pandas as pd
df = pd.DataFrame("Privileges":['Type1','Type2','Type3'],"Super_Admin":["A1,A2,A3,A4","A1,B1,B2,B3, A4","C1,B2,C2,C3"], "Admin":["A1,A2","A1,B1,B2","B2, C1,C2"])
Index Privileges Super_Admin Admin
0 Type1 A1,A2,A3,A4 A1,A2
1 Type2 A1,B1,B2,B3, A4 A1,B1,B2
2 Type3 C1,B2,C2,C3 B2, C1,C2

变换后的df

df = pd.DataFrame("Privileges":['Type1','Type1','Type1','Type1','Type2','Type2','Type2','Type2','Type2','Type3','Type3','Type3','Type3'],"Super_Admin":["A1","A2","A3","A4","A1", "B1","B2","B3", "A4","C1","B2","C2","C3"], "Admin":["A1","A2",'', '',"A1","B1","B2",'', '', "B2", "C1","C2", ''])
Index Privileges Super_Admin Admin
0 Type1 A1 A1
1 Type1 A2 A2
2 Type1 A3 --
3 Type1 A4 --
4 Type2 A1 A1
5 Type2 B1 B1
6 Type2 B2 B2
7 Type2 B3 --
8 Type2 A4 --
9 Type3 C1 B2
10 Type3 B2 C1
11 Type3 C2 C2
12 Type3 C3 --

【问题讨论】:

也感谢您分享数据帧代码。大多数人只是共享图片或文本数据框。你有完整的代码。它可以帮助我们快速解决问题。 Type 3 是否应该有 Super_Admin 和 Admin 匹配的值。例如:它有 C1 B2 和 B2 C1。应该是 C1 C1 和 B2 B2 吗? 查看几年前exploding multiple columns...上的帖子 【参考方案1】:

以下步骤的细分:

zip所有列

使用zip_longest 将None 与没有配对的值配对

将两个列表合二为一,chain

Privileges 列上创建数据框和forward fill

In [541]: step1 = zip(df.Privileges, df.Super_Admin, df.Admin)

In [542]: step2 = (zip_longest([first], second,last) 
                   for first, second, last 
                   in step1)

In [543]: step3 = chain.from_iterable(step2)

In [546]: (pd.DataFrame(step3, columns = df.columns)
             .assign(Privileges = lambda df: df.Privileges.ffill())
           )
Out[546]: 
   Privileges Super_Admin Admin
0       Type1          A1    A1
1       Type1          A2    A2
2       Type1          A3  None
3       Type1          A4  None
4       Type2          A1    A1
5       Type2          B1    B1
6       Type2          B2    B2
7       Type2          B3  None
8       Type2          A4  None
9       Type3          C1    B2
10      Type3          B2    C1
11      Type3          C2    C2
12      Type3          C3  None

为了获得更快的速度,您可以将拆分步骤移至原生 python 领域。 pandas 字符串方法是 Python 字符串函数的包装器,因此它们不如 Python 字符串函数快。

【讨论】:

太快了 :) 我刚开始,你已经有了。我的会太复杂。这看起来很整洁。赞成。【参考方案2】:

这是选项。 首先将Super_AdminAdmin 添加到列表中。这对于使用pd.explode() 很有用。

df['Super_Admin'] = df['Super_Admin'].apply(lambda x: x.split(','))
df['Admin'] = df['Admin'].apply(lambda x: x.split(','))

然后在两列上调用explode,并用空字符串填充缺失值。

a = df.explode('Super_Admin')
b = df.explode('Admin')
for i in range(3):
    short = b.loc[i,'Admin'].values
    long = a.loc[i,'Admin'].values
    a.loc[i,'Admin'] = np.concatenate((short, ['']*(len(long)-len(short))), axis=0)

输出如下所示:

>>> a
  Privileges Super_Admin Admin
0      Type1          A1    A1
0      Type1          A2    A2
0      Type1          A3      
0      Type1          A4      
1      Type2          A1    A1
1      Type2          B1    B1
1      Type2          B2    B2
1      Type2          B3      
1      Type2          A4      
2      Type3          C1    B2
2      Type3          B2    C1
2      Type3          C2    C2
2      Type3          C3      

【讨论】:

【参考方案3】:

您可以使用单个虽然基本上是链式的指令来完成这项工作:

result = df.set_index('Privileges').apply(lambda col:
    col.str.split(', ?', expand=True).stack())\
    .droplevel(1).reset_index().fillna('')

步骤:

df.set_index('Privileges') - 将 Privileges 设置为索引列。 apply(lambda col: - 应用于每一列: col.str.split(', ?', expand=True) - 将此列分成单独的 列(DataFrame,列名称为连续整数)。 stack() - 将上面的 DataFrame 转换成带有列的 Series 命名为第二个 MultiIndex 级别。 droplevel(1) - 删除不必要的索引级别。 reset_index() - 将 Privileges(索引列)更改为常规列。 fillna('') - 将每个 NaN 更改为空字符串。

结果是:

   Privileges Super_Admin Admin
0       Type1          A1    A1
1       Type1          A2    A2
2       Type1          A3      
3       Type1          A4      
4       Type2          A1    A1
5       Type2          B1    B1
6       Type2          B2    B2
7       Type2          B3      
8       Type2          A4      
9       Type3          C1    B2
10      Type3          B2    C1
11      Type3          C2    C2
12      Type3          C3      

【讨论】:

以上是关于将 pandas 中的一个单元格拆分为多行的主要内容,如果未能解决你的问题,请参考以下文章

excel 里如何把一列单元格拆分成两列

excel表格中单元格不能拆分只能合并对吗?

将多行单元拆分为不同的行

将 Pandas 单元格中的列表拆分为多列 [重复]

将单元格中的字符串拆分为不同的行,pandas [关闭]

将单元格中的多个值拆分为多行 - Oracle SQL