如何对每行都有列表的数据帧进行一次性编码
How to one-hot encode a dataframe where each row has lists
我正在尝试将数据列表中包含列表的数据提供给机器学习算法:
例如,一个病人可能有几种药物和对药物的几种反应,他们也可能有名字。因此,如果他们服用超过 1 种药物,它将以 2 种或更多的列表形式出现。他们只有一个名字。
我相信单热编码是正确的方法。
这是我到目前为止所做的:
我有一个数据框:
df = pandas.DataFrame([{'drug': ['drugA','drugB'], 'patient': 'john'}, {'drug': ['drugC','drugD'], 'patient': 'angel'}])
drug patient
0 [drugA, drugB] john
1 [drugC, drugD] angel
我想得到类似的东西:
drugA drugB drugC drugD patient
0 1 1 0 0 john
0 0 0 1 1 angel
我试过这个:
pandas.get_dummies(df.apply(pandas.Series).stack()).sum(level=0)
但是得到了:
TypeError: unhashable type: 'list'
大量借鉴 this answer,这是一种方法:
df = pd.DataFrame([{'drug': ['drugA','drugB'], 'patient': 'john'},
{'drug': ['drugC','drugD'], 'patient': 'angel'}])
s = df.drug
.apply(lambda x: pd.Series(x))
.unstack()
df2 = df.join(pd.DataFrame(s.reset_index(level=0, drop=True)))
.drop('drug',1)
.rename(columns={0:'drug'})
df2.merge(pd.get_dummies(df2.drug), left_index=True, right_index=True)
.drop('drug',1)
输出:
patient drugA drugB drugC drugD
0 john 1.0 0.0 0.0 0.0
0 john 0.0 1.0 0.0 0.0
0 john 1.0 0.0 0.0 0.0
0 john 0.0 1.0 0.0 0.0
1 angel 0.0 0.0 1.0 0.0
1 angel 0.0 0.0 0.0 1.0
1 angel 0.0 0.0 1.0 0.0
1 angel 0.0 0.0 0.0 1.0
使用:
通过values
and numpy.ndarray.tolist
创建新的DataFrame
pandas.get_dummies
groupby
+ max
concat
到原来的
df1 = pd.get_dummies(pd.DataFrame(df.pop('drug').values.tolist()), prefix='', prefix_sep='')
.groupby(axis=1, level=0).max()
df1 = pd.concat([df1, df], axis=1)
print (df1)
drugA drugB drugC drugD patient
0 1 1 0 0 john
1 0 0 1 1 angel
df1 = pd.get_dummies(pd.DataFrame(df['drug'].values.tolist()), prefix='', prefix_sep='') \
.groupby(axis=1, level=0).max()
df1 = pd.concat([df1, df.drop('drug', axis=1)], axis=1)
print (df1)
drugA drugB drugC drugD patient
0 1 1 0 0 john
1 0 0 1 1 angel
replace
+ str.get_dummies
concat
到原来的
df1 = df.pop('drug').astype(str).replace(['\[','\]', "'", "\s+"], '', regex=True)
.str.get_dummies(',')
df1 = pd.concat([df1, df], axis=1)
print (df1)
drugA drugB drugC drugD patient
0 1 1 0 0 john
1 0 0 1 1 angel
df1 = df['drug'].astype(str).replace(['\[','\]', "'", "\s+"], '', regex=True)
.str.get_dummies(',')
df1 = pd.concat([df1, df.drop('drug', axis=1)], axis=1)
print (df1)
drugA drugB drugC drugD patient
0 1 1 0 0 john
1 0 0 1 1 angel
我正在尝试将数据列表中包含列表的数据提供给机器学习算法:
例如,一个病人可能有几种药物和对药物的几种反应,他们也可能有名字。因此,如果他们服用超过 1 种药物,它将以 2 种或更多的列表形式出现。他们只有一个名字。
我相信单热编码是正确的方法。
这是我到目前为止所做的:
我有一个数据框:
df = pandas.DataFrame([{'drug': ['drugA','drugB'], 'patient': 'john'}, {'drug': ['drugC','drugD'], 'patient': 'angel'}])
drug patient
0 [drugA, drugB] john
1 [drugC, drugD] angel
我想得到类似的东西:
drugA drugB drugC drugD patient
0 1 1 0 0 john
0 0 0 1 1 angel
我试过这个:
pandas.get_dummies(df.apply(pandas.Series).stack()).sum(level=0)
但是得到了:
TypeError: unhashable type: 'list'
大量借鉴 this answer,这是一种方法:
df = pd.DataFrame([{'drug': ['drugA','drugB'], 'patient': 'john'},
{'drug': ['drugC','drugD'], 'patient': 'angel'}])
s = df.drug
.apply(lambda x: pd.Series(x))
.unstack()
df2 = df.join(pd.DataFrame(s.reset_index(level=0, drop=True)))
.drop('drug',1)
.rename(columns={0:'drug'})
df2.merge(pd.get_dummies(df2.drug), left_index=True, right_index=True)
.drop('drug',1)
输出:
patient drugA drugB drugC drugD
0 john 1.0 0.0 0.0 0.0
0 john 0.0 1.0 0.0 0.0
0 john 1.0 0.0 0.0 0.0
0 john 0.0 1.0 0.0 0.0
1 angel 0.0 0.0 1.0 0.0
1 angel 0.0 0.0 0.0 1.0
1 angel 0.0 0.0 1.0 0.0
1 angel 0.0 0.0 0.0 1.0
使用:
通过
values
andnumpy.ndarray.tolist
创建新的pandas.get_dummies
groupby
+max
concat
到原来的
DataFrame
df1 = pd.get_dummies(pd.DataFrame(df.pop('drug').values.tolist()), prefix='', prefix_sep='')
.groupby(axis=1, level=0).max()
df1 = pd.concat([df1, df], axis=1)
print (df1)
drugA drugB drugC drugD patient
0 1 1 0 0 john
1 0 0 1 1 angel
df1 = pd.get_dummies(pd.DataFrame(df['drug'].values.tolist()), prefix='', prefix_sep='') \
.groupby(axis=1, level=0).max()
df1 = pd.concat([df1, df.drop('drug', axis=1)], axis=1)
print (df1)
drugA drugB drugC drugD patient
0 1 1 0 0 john
1 0 0 1 1 angel
replace
+str.get_dummies
concat
到原来的
df1 = df.pop('drug').astype(str).replace(['\[','\]', "'", "\s+"], '', regex=True)
.str.get_dummies(',')
df1 = pd.concat([df1, df], axis=1)
print (df1)
drugA drugB drugC drugD patient
0 1 1 0 0 john
1 0 0 1 1 angel
df1 = df['drug'].astype(str).replace(['\[','\]', "'", "\s+"], '', regex=True)
.str.get_dummies(',')
df1 = pd.concat([df1, df.drop('drug', axis=1)], axis=1)
print (df1)
drugA drugB drugC drugD patient
0 1 1 0 0 john
1 0 0 1 1 angel