【问题标题】:How could I do one hot encoding with multiple values in one cell?如何在一个单元格中使用多个值进行一次热编码?
【发布时间】:2016-06-05 20:32:21
【问题描述】:

我在 Excel 中有这张表:

id  class
0   2 3
1   1 3 
2   3 5

现在,我想在 Python 中做一个“特殊”的 one-hot 编码。 对于第一个表中的每个 id,都有两个数字。每个数字对应一个类(class1、class2 等)。第二个表是基于第一个表创建的,这样对于每个 id,其行中的每个数字都显示在其相应的类列中,而其他列则为零。例如,id 0 的数字是 2 和 3。2 放置在 class2 中,3 放置在 class3 中。类 1、4 和 5 的默认值为 0。结果应如下所示:

id  class1  class2  class3  class4  class5
 0   0       2        3       0       0
 1   1       0        3       0       0
 2   0       0        3       0       5

我之前的解决方案,

foo = lambda x: pd.Series([i for i in x.split()])
result=onehot['hotel'].apply(foo)
result.columns=['class1','class2']
pd.get_dummies(result, prefix='class', columns=['class1','class2'])

结果:

    class_1 class_2 class_3 class_3 class_5
  0  0.0     1.0    0.0      1.0    0.0
  1  1.0     0.0    0.0      1.0    0.0
  2  0.0     0.0    1.0      0.0    1.0

(class_3 出现两次)。我能做些什么来解决这个问题? (经过这一步,我可以把它转换成我想要的最终格式。)

【问题讨论】:

  • @FengLi 请注意。像您所做的那样存储lambda 函数违背了它们的目的。你可以改用def

标签: python one-hot-encoding


【解决方案1】:

您需要将变量设置为categorical,然后您可以使用one hot encoding,如图所示:

In [18]: df1 = pd.DataFrame({"class":pd.Series(['2','1','3']).astype('category',categories=['1','2','3','4','5'])})

In [19]: df2 = pd.DataFrame({"class":pd.Series(['3','3','5']).astype('category',categories=['1','2','3','4','5'])})

In [20]: df_1 = pd.get_dummies(df1)

In [21]: df_2 = pd.get_dummies(df2)

In [22]: df_1.add(df_2).apply(lambda x: x * [i for i in range(1,len(df_1.columns)+1)], axis = 1).astype(int).rename_axis('id')
Out[22]: 
    class_1  class_2  class_3  class_4  class_5
id                                             
0         0        2        3        0        0
1         1        0        3        0        0
2         0        0        3        0        5

【讨论】:

    【解决方案2】:

    这是否满足您所说的问题?

    #!/usr/bin/python
    
    input = [
        (0, (2,3)),
        (1, (1,3)),
        (2, (3,5)),
    ]
    
    maximum = max(reduce(lambda x, y: x+list(y[1]), input, []))
    # Or ...
    # maximum = 0
    # for i, classes in input:
    #    maximum = max(maximum, *classes)
    
    # print header.
    print "\t".join(["id"] + ["class_%d" % i for i in range(1, 6)])
    
    for i, classes in input:
        print i,
        for r in range(1, maximum+1):
            print "\t",
            if r in classes:
                print float(r),
            else:
                print 0.0,
        print
    

    输出:

    id      class_1 class_2 class_3 class_4 class_5
    0       0.0     2.0     3.0     0.0     0.0
    1       1.0     0.0     3.0     0.0     0.0
    2       0.0     0.0     3.0     0.0     5.0
    

    【讨论】:

      【解决方案3】:

      将原始数据框拆分为 3 列可能更简单:

      id  class_a class_b
      0   2          3
      1   1          3  
      2   3          5
      

      然后对其执行正常的 one-hot 编码。之后,您可能会得到重复的列,例如:

      id  ... class_a_3 class_b_3 ... class_b_5
      0          0          1             0
      1          0          1             0
      2          1          0             0
      

      但是您可以在事后非常简单地合并/求和它们。

      同样,您可以使用相同的逻辑并将您的 df 转换为以下形式:

      id  class
      0   2
      0   3         
      1   1
      1   3         
      2   3
      2   5
      

      然后 one-hot ,并在 key id 上使用 sum 聚合。

      【讨论】:

        【解决方案4】:

        这个怎么样?

        鉴于此数据

        import pandas as pd
        df = pd.DataFrame({'id': [0, 1, 2], 'class': ['2 3', '1 3', '3 5']})
        

        1- 拆分值

        df['class'] = df['class'].apply(lambda x: x.split(' '))
        
        df
           id   class
        0   0  [2, 3]
        1   1  [1, 3]
        2   2  [3, 5]
        

        2- explode --> 一行中的每条记录

        df_long = df.explode('class')
        
        df_long
           id class
        0   0     2
        0   0     3
        1   1     1
        1   1     3
        2   2     3
        2   2     5
        

        3- 获取一个热编码值

        df_one_hot_encoded = pd.concat([df, pd.get_dummies(df_long['class'],prefix='class', prefix_sep='_')], axis=1)
        
        df_one_hot_encoded
           id   class  class_1  class_2  class_3  class_5
        0   0  [2, 3]        0        1        0        0
        0   0  [2, 3]        0        0        1        0
        1   1  [1, 3]        1        0        0        0
        1   1  [1, 3]        0        0        1        0
        2   2  [3, 5]        0        0        1        0
        2   2  [3, 5]        0        0        0        1
        

        4- groupby id 并获得每列的最大值(二进制值的逻辑或结果相同)--> 每个 id 一行

        df_one_hot_encoded.groupby('id').max().reset_index()
        
           id   class  class_1  class_2  class_3  class_5
        0   0  [2, 3]        0        1        1        0
        1   1  [1, 3]        1        0        1        0
        2   2  [3, 5]        0        0        1        1
        

        大家齐心协力

        import pandas as pd
        df = pd.DataFrame({'id': [0, 1, 2], 'class': ['2 3', '1 3', '3 5']})
        df['class'] = df['class'].apply(lambda x: x.split(' '))
        df_long = df.explode('class')
        df_one_hot_encoded = pd.concat([df, pd.get_dummies(df_long['class'],prefix='class', prefix_sep='_')], axis=1)
        df_one_hot_encoded_compact = df_one_hot_encoded.groupby('id').max().reset_index()
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-07-16
          • 2022-09-27
          • 2017-06-08
          • 2023-01-10
          • 2020-05-30
          • 2021-02-10
          • 1970-01-01
          相关资源
          最近更新 更多