【问题标题】:One-hot encoding across multiple columns - but as one group跨多列的单热编码 - 但作为一组
【发布时间】:2020-11-04 08:16:17
【问题描述】:
我有一个 Python Pandas 数据框:
Name Item1 Item2 Item3
John Sword
Mary Shield Ring
Doe Ring Sword
期望的输出:
Name Item-Sword Item-Shield Item-Ring
John 1 0 0
Mary 0 1 1
Doe 1 0 1
这有什么方法可以在手动处理之外实现吗?
【问题讨论】:
标签:
python
pandas
dataframe
【解决方案1】:
使用get_dummies 和转换Name 列来索引并仅删除缺失值列,然后在输出中使用max 仅0,1 值,添加前缀并将索引转换为列:
df = (pd.get_dummies(df.set_index('Name')
.dropna(axis=1, how='all'), prefix='', prefix_sep='')
.max(axis=1, level=0)
.add_prefix('Item-')
.reset_index())
print (df)
Name Item-Ring Item-Shield Item-Sword
0 John 0 0 1
1 Mary 1 1 0
2 Doe 1 0 1
melt 和 crosstab 的替代方案 - @sammywemmy 解决方案,drop_duplicates:
df1 = (df.melt("Name")
.assign(value=lambda x: "Item-" + x.value)
.drop_duplicates(['Name','value']))
df1 = pd.crosstab(df1.Name, df1.value)
print (df1)
value Item-Ring Item-Shield Item-Sword
Name
Doe 1 0 1
John 0 0 1
Mary 1 1 0
【解决方案2】:
DataFrame.melt + DataFrame.groupby 的另一种解决方案
new_df = (df.melt('Name').groupby(['Name', 'value'])
.count()
.clip(0, 1)
.unstack('value', fill_value=0)
.droplevel(0, axis=1)
.add_prefix('Item-')
.rename_axis(columns=None)
.reset_index())
print(new_df)
或DataFrame.pivot_table
df2 = df.melt('Name')
new_df = (df2.pivot_table(index='Name', columns='value', values='variable',
aggfunc='any', fill_value=0)
.astype(int)
.add_prefix('Item-')
.rename_axis(columns=None)
.reset_index())
print(new_df)
输出
Name Item-Ring Item-Shield Item-Sword
0 Doe 1 0 1
1 John 0 0 1
2 Mary 1 1 0
【解决方案3】:
如果将索引设置为"Name",然后将stack() 数据设置为单个Series,则可以使用pd.get_dummies 对数据进行编码。然后你需要使用max 来获得每个"Name" 的最大值(这个逻辑归结为:我们不关心"Mary" 是否有一个环作为项目1 或项目2,只要她有一个环)。完成后,我们可以通过添加前缀并将索引重置回DataFrame来进行整理
out = (df.set_index("Name")
.stack()
.pipe(pd.get_dummies)
.max(level="Name")
.add_prefix("Item-")
.reset_index())
print(out)
Name Item-Ring Item-Shield Item-Sword
0 John 0 0 1
1 Mary 1 1 0
2 Doe 1 0 1