我在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。
答案 0 :(得分:5)
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
。
我想出了使用stack
,pivot_table
,np.where
和pd.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