给定数据帧df1
如下:
df1 = pd.DataFrame({
'col1': [1,2,3,4],
'col2': [['a', 'b'], ['c'], ['a', 'd', 'b'], ['e']]
})
看起来像:
col1 col2
0 1 [a, b]
1 2 [c]
2 3 [a, d, b]
3 4 [e]
我想将col2
(每个单元格都是列表的列(转换为多个列(a
、b
、c
、d
、e
(,其中的值是布尔条目,定义该列名是否存在于给定行的原始列表中。
输出应遵循以下形式:
df2 = pd.DataFrame({
'col1': [1,2,3,4],
'a': [True, False, True, False],
'b': [True, False, True, False],
'c': [False, True, False, False],
'd': [False, False, True, False],
'e': [False, False, False, True]
})
看起来像:
col1 a b c d e
0 1 True True False False False
1 2 False False True False False
2 3 True True False True False
3 4 False False False False True
什么是干净的方法?
使用str.get_dummies
的替代方法可能比apply
+pd.Series
:更有效
df1['col2'].str.join(',').str.get_dummies(sep=',').astype(bool)
a b c d e
0 True True False False False
1 False False True False False
2 True True False True False
3 False False False False True
计时:
df1.shape
(40000, 2)
%%timeit
df1['col2'].str.join(',').str.get_dummies(sep=',').astype(bool)
286 ms ± 16.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%%timeit
pd.get_dummies(df1['col2'].apply(pd.Series).stack()).sum(level=0)
9.43 s ± 499 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
一种方法
df2 = df1.reset_index().explode('col2')
new_df = pd.crosstab(df2['col1'], df2['col2']).astype(bool)
print(new_df)
col2 a b c d e
col1
1 True True False False False
2 False False True False False
3 True True False True False
4 False False False False True
或
new_df = (df1.reset_index()
.explode('col2')
.groupby(['index', 'col2'])['col1']
.any()
.unstack(fill_value=False))
new_df = (df1.reset_index()
.explode('col2')
.pivot_table(index='index',
values='col1',
columns='col2',
aggfunc='any',
fill_value=False)
)
已解决。
pd.get_dummies(df1['col2'].apply(pd.Series).stack()).sum(level=0)