在 Pandas 中反转“独热”编码

2025-02-27 09:07:00
admin
原创
56
摘要:问题描述:我想要从这个基本上是独热编码的数据框开始。 In [2]: pd.DataFrame({"monkey":[0,1,0],"rabbit":[1,0,0],"fox":[0,0,1]}) Out[2]: fox m...

问题描述:

我想要从这个基本上是独热编码的数据框开始。

 In [2]: pd.DataFrame({"monkey":[0,1,0],"rabbit":[1,0,0],"fox":[0,0,1]})

    Out[2]:
       fox  monkey  rabbit
    0    0       0       1
    1    0       1       0
    2    1       0       0
    3    0       0       0
    4    0       0       0

对于这个“反向”独热编码。

    In [3]: pd.DataFrame({"animal":["monkey","rabbit","fox"]})
    Out[3]:
       animal
    0  monkey
    1  rabbit
    2     fox

我想象可以巧妙地使用 apply 或 zip 来进行稀释,但我不确定如何...有人可以帮忙吗?

我尝试使用索引等方法来解决这个问题,但是并没有取得多大成功。


解决方案 1:

更新:正如 Henry Ecker 在他的回答中提到的那样,从 Pandas 1.5.0 开始,有一个原生的 Pandas 方法可以做到这一点 - pandas.from_dummies()

演示:

In [35]: s = pd.Series(['dog', 'cat', 'dog', 'bird', 'fox', 'dog'])

In [36]: dummies = pd.get_dummies(s)

In [37]: dummies
Out[37]:
   bird  cat  dog  fox
0     0    0    1    0
1     0    1    0    0
2     0    0    1    0
3     1    0    0    0
4     0    0    0    1
5     0    0    1    0

In [38]: pd.from_dummies(dummies)
Out[38]:

0   dog
1   cat
2   dog
3  bird
4   fox
5   dog

注意:pd.from_dummies()如果使用参数创建虚拟对象,则可能无法正常工作,drop_first=True例如:pd.get_dummies(data, drop_first=True)

演示:

In [39]: dummies = pd.get_dummies(s, drop_first=True)

In [40]: dummies
Out[40]:
   cat  dog  fox
0    0    1    0
1    1    0    0
2    0    1    0
3    0    0    0
4    0    0    1
5    0    1    0

In [41]: pd.from_dummies(dummies)
...
ValueError: Dummy DataFrame contains unassigned value(s); First instance in row: 3

旧答案:我认为ayhan是正确的,应该是:

df.idxmax(axis=1)

这将为每行选择一个列标签,其中标签具有最大值。由于数据为 1 和 0,因此它将选择 1 的位置。

演示:

In [40]: s = pd.Series(['dog', 'cat', 'dog', 'bird', 'fox', 'dog'])

In [41]: s
Out[41]:
0     dog
1     cat
2     dog
3    bird
4     fox
5     dog
dtype: object

In [42]: pd.get_dummies(s)
Out[42]:
   bird  cat  dog  fox
0   0.0  0.0  1.0  0.0
1   0.0  1.0  0.0  0.0
2   0.0  0.0  1.0  0.0
3   1.0  0.0  0.0  0.0
4   0.0  0.0  0.0  1.0
5   0.0  0.0  1.0  0.0

In [43]: pd.get_dummies(s).idxmax(1)
Out[43]:
0     dog
1     cat
2     dog
3    bird
4     fox
5     dog
dtype: object

解决方案 2:

我将使用 apply 来解码列:

In [2]: animals = pd.DataFrame({"monkey":[0,1,0,0,0],"rabbit":[1,0,0,0,0],"fox":[0,0,1,0,0]})

In [3]: def get_animal(row):
   ...:     for c in animals.columns:
   ...:         if row[c]==1:
   ...:             return c

In [4]: animals.apply(get_animal, axis=1)
Out[4]: 
0    rabbit
1    monkey
2       fox
3      None
4      None
dtype: object

解决方案 3:

这适用于单个标签和多个标签。

我们可以使用高级索引来解决这个问题。这是链接。

import pandas as pd

df = pd.DataFrame({"monkey":[1,1,0,1,0],"rabbit":[1,1,1,1,0],\n    "fox":[1,0,1,0,0], "cat":[0,0,0,0,1]})

df['tags']='' # to create an empty column

for col_name in df.columns:
    df.ix[df[col_name]==1,'tags']= df['tags']+' '+col_name

print df

结果是:

   cat  fox  monkey  rabbit                tags
0    0    1       1       1   fox monkey rabbit
1    0    0       1       1       monkey rabbit
2    0    1       0       1          fox rabbit
3    0    0       1       1       monkey rabbit
4    1    0       0       0                 cat

解释:我们迭代数据框上的列。

df.ix[selection criteria, columns to write value] = value
df.ix[df[col_name]==1,'tags']= df['tags']+' '+col_name

上面这一行基本上找到了 df[col_name] == 1 的所有位置,选择列“tags”并将其设置为 RHS 值,即 df['tags']+' '+ col_name

注意: .ix自 Pandas v0.20 起已弃用。您应根据需要使用.loc.iloc

解决方案 4:

从pandas 1.5.0开始,直接支持反转独热编码pandas.from_dummies

import pandas as pd  # v 1.5.0

onehot_df = pd.DataFrame({
    "monkey": [0, 1, 0],
    "rabbit": [1, 0, 0],
    "fox": [0, 0, 1]
})

new_df = pd.from_dummies(onehot_df)

#          
# 0  rabbit
# 1  monkey
# 2     fox

生成的 DataFrame 似乎没有列标题(它是一个空字符串)。为了解决这个问题,rename后面的列from_dummies

new_df = pd.from_dummies(onehot_df).rename(columns={'': 'animal'})

#    animal
# 0  rabbit
# 1  monkey
# 2     fox

或者,如果 DataFrame 已经定义了分隔列(例如由 生成的独热编码pandas.get_dummies),例如

import pandas as pd  # v 1.5.0

onehot_df = pd.DataFrame({
    'animal_fox': [0, 0, 1],
    'animal_monkey': [0, 1, 0],
    'animal_rabbit': [1, 0, 0]
})

#    animal_fox  animal_monkey  animal_rabbit
# 0           0              0              1
# 1           0              1              0
# 2           1              0              0

只需指定sep反转编码

new_df = pd.from_dummies(onehot_df, sep='_')

#    animal
# 0  rabbit
# 1  monkey
# 2     fox

分隔符第一个实例之前的字符串sep将成为新 DataFrame 中的列标题(在本例中为“animal”),字符串的其余部分将成为列值(在本例中为“rabbit”、“monkey”、“fox”)。

解决方案 5:

我会这么做:

cols = df.columns.to_series().values
pd.DataFrame(np.repeat(cols[None, :], len(df), 0)[df.astype(bool).values], df.index[df.any(1)])

在此处输入图片描述


定时

MaxU 的方法对大型数据帧有优势

df5 x 3

在此处输入图片描述

df1000000 x 52

在此处输入图片描述

解决方案 6:

您可以尝试使用melt()。当一行有多个 OHE 标签时,此方法也有效。

# Your OHE dataframe 
df = pd.DataFrame({"monkey":[0,1,0],"rabbit":[1,0,0],"fox":[0,0,1]})

mel = df.melt(var_name=['animal'], value_name='value') # Melting

mel[mel.value == 1].reset_index(drop=True) # this gives you the result 

解决方案 7:

尝试一下:

df = pd.DataFrame({"monkey":[0,1,0,1,0],"rabbit":[1,0,0,0,0],"fox":[0,0,1,0,0], "cat":[0,0,0,0,1]})
df 

   cat  fox  monkey  rabbit
0    0    0       0       1
1    0    0       1       0
2    0    1       0       0
3    0    0       1       0
4    1    0       0       0

pd.DataFrame([x for x in np.where(df ==1, df.columns,'').flatten().tolist() if len(x) >0],columns= (["animal"]) )

   animal
0  rabbit
1  monkey
2     fox
3  monkey
4     cat

解决方案 8:

只需在数据框上简单应用即可实现

# function to get column name with value one for each row in dataframe
def get_animal(row):
    return(row.index[row.apply(lambda x: x==1)][0])

# prepare a animal column
df['animal'] = df.apply(lambda row:get_animal(row), axis=1)

解决方案 9:

一种无需 for 循环即可处理多个标签的方法。结果将是一个列表列。如果每行的标签数量相同,则可以添加result_type='expand'以获得多列。

df.apply(lambda x: df.columns[x==1], axis=1)
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   2941  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1803  
  PLM(产品生命周期管理)系统在企业的产品研发、生产与管理过程中扮演着至关重要的角色。然而,在实际运行中,资源冲突是经常会遇到的难题。资源冲突可能导致项目进度延迟、成本增加以及产品质量下降等一系列问题,严重影响企业的效益与竞争力。因此,如何有效应对PLM系统中的资源冲突,成为众多企业关注的焦点。接下来,我们将详细探讨5...
plm项目管理系统   31  
  敏捷项目管理与产品生命周期管理(PLM)的融合,正成为企业在复杂多变的市场环境中提升研发效率、增强竞争力的关键举措。随着技术的飞速发展和市场需求的快速更迭,传统的研发流程面临着诸多挑战,而将敏捷项目管理理念融入PLM,有望在2025年实现研发流程的深度优化,为企业创造更大的价值。理解敏捷项目管理与PLM的核心概念敏捷项...
plm项目   31  
  模块化设计在现代产品开发中扮演着至关重要的角色,它能够提升产品开发效率、降低成本、增强产品的可维护性与可扩展性。而产品生命周期管理(PLM)系统作为整合产品全生命周期信息的关键平台,对模块化设计有着强大的支持能力。随着技术的不断发展,到 2025 年,PLM 系统在支持模块化设计方面将有一系列令人瞩目的技术实践。数字化...
plm软件   28  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用