【问题标题】:Reversing 'one-hot' encoding in Pandas在 Pandas 中反转“one-hot”编码
【发布时间】:2016-11-15 00:21:57
【问题描述】:

我想从这个基本上是一个热编码的数据帧开始。

 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 来做薄,但我不知道如何......有人可以帮忙吗?

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

【问题讨论】:

  • 请向我们展示您的代码。
  • 您的 2 个数据框不匹配...
  • 我解决了这个问题 - 感谢您的关注 :)
  • @PeadarCoyle,您能否为该输入 DF 发布您想要的 DF:pd.DataFrame({'dog': {0: 0, 1: 0, 2: 0, 3: 0, 4: 0, 5: 1}, 'fox': {0: 0, 1: 0, 2: 1, 3: 0, 4: 0, 5: 0}, 'monkey': {0: 0, 1: 1, 2: 0, 3: 0, 4: 0, 5: 0}, 'rabbit': {0: 1, 1: 0, 2: 0, 3: 0, 4: 0, 5: 0}}),因为现在我不明白您想要的 DF?
  • @PeadarCoyle,您能否澄清一下您的输入数据集在一列中是否可能包含多个1?你是如何得到只包含零的行的?

标签: python pandas dataframe


【解决方案1】:

可以通过对数据框的简单应用来实现

# 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)

【讨论】:

    【解决方案2】:

    您可以尝试使用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 
    

    【讨论】:

      【解决方案3】:

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

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

      import pandas as pd
      
      df = pd.DataFrame({"monkey":[1,1,0,1,0],"rabbit":[1,1,1,1,0],\
          "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】:

        更新:我认为ayhan 是正确的,应该是:

        df.idxmax(axis=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
        

        旧答案:(很可能是错误答案)

        试试这个:

        In [504]: df.idxmax().reset_index().rename(columns={'index':'animal', 0:'idx'})
        Out[504]:
           animal  idx
        0     fox    2
        1  monkey    1
        2  rabbit    0
        

        数据:

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

        【讨论】:

        • 如果任何列重复会发生什么。说两只猴子? [1,3] 这会捡起来吗。
        • 不应该是df.idxmax(axis=1)吗?
        • @ayhan,它看起来好多了,但不幸的是,它并不总是能正常工作!
        • @ayhan,试试这个 DF:pd.DataFrame({'dog': {0: 0, 1: 0, 2: 0, 3: 0, 4: 0, 5: 1}, 'fox': {0: 0, 1: 0, 2: 1, 3: 0, 4: 0, 5: 0}, 'monkey': {0: 0, 1: 1, 2: 0, 3: 0, 4: 0, 5: 0}, 'rabbit': {0: 1, 1: 0, 2: 0, 3: 0, 4: 0, 5: 0}})
        • 实际上应该是每行一个1。你可以试试pd.Series(['dog', 'cat', 'dog', 'bird']).str.get_dummies()。 get_dummies 将始终生成这样的结构(连续不超过一个 1)。 OP的问题是有问题的。他们想要用于创建假人的原始数组,但示例中的顺序错误(应该是兔子、猴子、狐狸)。除此之外,就像我说的,在创建虚拟对象时删除其中一列是一种常见的做法(以避免多重共线性),但为了返回原始数组,我们必须知道该列是什么。
        【解决方案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 的方法对于大型数据帧具有优势

        df 5 x 3

        df 1000000 x 52

        【讨论】:

          【解决方案6】:

          试试这个:

          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
          

          【讨论】:

          • 我包含在更大数据帧的计时中。
          【解决方案7】:

          我会使用 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
          

          【讨论】:

          • 有没有办法在存在多个标签的情况下做到这一点,并为每一行返回一个标签列表?
          • 动物不在 get_animal 范围内
          猜你喜欢
          • 2023-01-16
          • 2020-10-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-02-16
          • 1970-01-01
          • 1970-01-01
          • 2018-01-26
          相关资源
          最近更新 更多