将数据框中具有多个值的单元格转换为多行

时间:2018-09-16 05:05:23

标签: python pandas

我的数据是这样的:

Name    test1     test2      Count
Emp1    X,Y        A           1
Emp2    X          A,B,C       2
Emp3    Z          C           3

我正在使用下面的代码将具有多个值的 test1 单元格拆分为单独的行。但是,我不确定如何拆分 Test2 列。

df2 = df.test1.str.split(',').apply(pd.Series)
df2.index = df.set_index(['Name', 'count']).index
df2.stack().reset_index(['Name', 'count'])
df2

输出为:

Name    test1   Count
Emp1    X        1
Emp1    Y        1
Emp2    X        2
Emp2    X        2
Emp2    X        2
Emp2    Z        3

我正在尝试拆分 test1 test2 ,以便实现以下输出:

Name    test1    test2  Count
Emp1    X          A      1
Emp1    Y          A      1
Emp2    X          A      2
Emp2    X          B      2
Emp2    X          C      2
Emp2    Z          C      3

有人可以帮忙吗?

3 个答案:

答案 0 :(得分:3)

我只是修复您的代码,因为我不建议您取消嵌套数据框的方法,因此您可以在此处检查answer,有多种不错的方法。

df2 = df.test1.str.split(',').apply(pd.Series)
df2.index = df.set_index(['Name', 'Count']).index
df2=df2.stack().reset_index(['Name', 'Count'])
df3 = df.test2.str.split(',').apply(pd.Series)
df3.index = df.set_index(['Name', 'Count']).index
df3=df3.stack().reset_index(['Name', 'Count'])

只需在这里merge

df2.merge(df3,on=['Name', 'Count'],how='outer')
Out[132]: 
   Name  Count 0_x 0_y
0  Emp1      1   X   A
1  Emp1      1   Y   A
2  Emp2      2   X   A
3  Emp2      2   X   B
4  Emp2      2   X   C
5  Emp3      3   Z   C

答案 1 :(得分:3)

我认为让this answer highlighted by @wen适应这个问题不是那么简单,所以我将提出一个解决方案。

您可以创建一个函数,该函数采用df,要扩展的列和该列的分隔符,并根据需要进行多次调用。

def expand(df, col, sep=','):
    r = df[col].str.split(sep)
    d = {c: df[c].values.repeat(r.str.len(), axis=0) for c in df.columns}
    d[col] = [i for sub in r for i in sub]
    return pd.DataFrame(d)

expand(expand(df, 'test1'), 'test2')

    Name    test1   test2   Count
0   Emp1    X       A       1
1   Emp1    Y       A       1
2   Emp2    X       A       2
3   Emp2    X       B       2
4   Emp2    X       C       2
5   Emp3    Z       C       3

假设您有

df['test3'] = ['X1|X2|X3', 'X4', 'X5']

如此

>>> print(df)

    Name    test1   test2   Count   test3
0   Emp1    X,Y     A       1       X1|X2|X3
1   Emp2    X       A,B,C   2       X4
2   Emp3    Z       C       3       X5

然后

>>> expand(df,'test3', '|')

    Name    test1   test2   Count   test3
0   Emp1    X,Y     A       1       X1
1   Emp1    X,Y     A       1       X2
2   Emp1    X,Y     A       1       X3
3   Emp2    X       A,B,C   2       X4
4   Emp3    Z       C       3       X5

如果您认为列大小可能会显着增加 ,则可以定义函数expand_all来避免出现类似expand(expand(expand(expand(........))))))的情况。例如:

def expand_all(df, cols, seps):
    ret = df
    for c,s in zip(cols,seps): ret = expand(ret,c,s)
    return ret

>>> expand_all(df, ['test1', 'test2', 'test3'], [',', ',', '|'])

    Name    test1   test2   Count   test3
0   Emp1    X       A       1       X1
1   Emp1    X       A       1       X2
2   Emp1    X       A       1       X3
3   Emp1    Y       A       1       X1
4   Emp1    Y       A       1       X2
5   Emp1    Y       A       1       X3
6   Emp2    X       A       2       X4
7   Emp2    X       B       2       X4
8   Emp2    X       C       2       X4
9   Emp3    Z       C       3       X5

还是适当的;)


详细信息:

>>> expand(df, 'test1')

    Name    test1   test2   Count
0   Emp1    X       A       1
1   Emp1    Y       A       1
2   Emp2    X       A,B,C   2
3   Emp3    Z       C       3

>>> expand(df, 'test2')

    Name    test1   test2   Count
0   Emp1    X,Y     A       1
1   Emp2    X       A       2
2   Emp2    X       B       2
3   Emp2    X       C       2
4   Emp3    Z       C       3

>>> expand(expand(df, 'test2'), 'test1') 

    Name    test1   test2   Count
0   Emp1    X       A       1
1   Emp1    Y       A       1
2   Emp2    X       A       2
3   Emp2    X       B       2
4   Emp2    X       C       2
5   Emp3    Z       C       3


>>> expand(expand(df, 'test2'), 'test1').eq(expand(expand(df, 'test1'), 'test2')).all()

Name     True
test1    True
test2    True
Count    True
dtype: bool

答案 2 :(得分:1)

理解力

pd.DataFrame(
    [(n, a, b, c)
     for n, A, B, c in zip(*map(df.get, df))
     for a in A.split(',') for b in B.split(',')],
    columns=df.columns
)

   Name test1 test2  Count
0  Emp1     X     A      1
1  Emp1     Y     A      1
2  Emp2     X     A      2
3  Emp2     X     B      2
4  Emp2     X     C      2
5  Emp3     Z     C      3