大熊猫:根据值将包含分号的列分为多个列

时间:2019-05-13 06:46:48

标签: python pandas csv dataframe

我在ddata.csv中的数据如下:

col1,col2,col3,col4
A,10,a;b;c, 20
B,30,d;a;b,40
C,50,g;h;a,60

我想将col3分成多个列,但要基于它们的值。在其他方面,我希望最终数据看起来像

col1, col2, name_a, name_b, name_c, name_d, name_g, name_h, col4
A,    10,   a,      b,      c,      NULL,   NULL,   NULL,   20
B,    30,   a,      b,      NULL,   d,      NULL,   NULL,   40
C,    50,   a,      NULL,   NULL,   NULL,   g,      h,      60

answer所引用的代码目前不完整:

import pandas as pd

import string
L = list(string.ascii_lowercase)

names = dict(zip(range(len(L)), ['name_' + x for x in  L]))
df = pd.read_csv('ddata.csv')
df2 = df['col3'].str.split(';', expand=True).rename(columns=names)

列名'a','b','c'...是随机抽取的,与实际数据a,b,c不相关。

现在,我的代码可以将'col3'分为以下三列:

name_a name_b name_c
a      b      c
d      e      f
g      h      i

但是,它应该像  name_a,name_b,name_c,name_d,name_g,name_h  a,b,c,NULL,NULL,NULL  a,b,NULL,d,NULL,NULL  a,NULL,NULL,NULL,g,h

最后,我只需要用这些多列替换col3。

2 个答案:

答案 0 :(得分:5)

使用Series.str.get_dummies

print (df['col3'].str.get_dummies(';'))
   a  b  c  d  g  h
0  1  1  1  0  0  0
1  1  1  0  1  0  0
2  1  0  0  0  1  1

要从原始用途DataFrame.pop中提取列col3,请用numpy中的列名称通过多个值创建新的DataFrame,用{{3 }}和DataFrame.where中的新列名称。

NaN

最后通过pos = df.columns.get_loc('col3') df2 = df.pop('col3').str.get_dummies(';').astype(bool) df2 = (pd.DataFrame(df2.values * df2.columns.values[ None, :], columns=df2.columns, index=df2.index) .where(df2) .add_prefix('name_')) 通过位置过滤的所有DataFrame通过DataFrame.add_prefix结合在一起:

iloc

答案 1 :(得分:0)

@jezrael解决方案非常好。直到现在我还不认识str.get_dummies

我想出了使用stackpivot_tablenp.wherepd.concat的解决方案

df1 = df.col3.str.split(';', expand=True).stack().reset_index(level=0)
df2 = pd.pivot_table(df1, index='level_0', columns=df1[0], aggfunc=len)

Out[1658]:
0          a    b    c    d    g    h
level_0
0        1.0  1.0  1.0  NaN  NaN  NaN
1        1.0  1.0  NaN  1.0  NaN  NaN
2        1.0  NaN  NaN  NaN  1.0  1.0

接下来,使用1.0用列名填充np.where,找到col3的索引,然后使用pd.concat构造最终的df

df2[:] = np.where(df2.isna(), np.nan, df2.columns)
i = df.columns.tolist().index('col3')
pd.concat([df.iloc[:,:i], df2.add_prefix('name_'), df.iloc[:,i+1:]], axis=1)

Out[1667]:
  col1  col2 name_a name_b name_c name_d name_g name_h  col4
0    A    10      a      b      c    NaN    NaN    NaN    20
1    B    30      a      b    NaN      d    NaN    NaN    40
2    C    50      a    NaN    NaN    NaN      g      h    60