如何将非一个热编码转换为同一行上具有多个值的列

问题描述

我基本上想颠倒this question中提出的过程。

>>> import pandas as pd
>>> example_input = pd.DataFrame({"one"   : [0,1,0],"two"   : [0,"three" : [1,"four"  : [1,0]
                                  })
>>> print(example_input)
   one  two  three  four
0    0    0      1     1
1    1    0      1     1
2    0    0      1     0
3    1    0      1     0
4    0    0      0     0
>>> desired_output = pd.DataFrame(["three,four","one,three,"three",three",""])
>>> print(desired_output)
                  0
0       three,four
1  one,four
2             three
3        one,three
4                  

关于逆向一热编码有很多问题(示例12),但是答案仅依赖于每行有效的一个二进制类,而我的数据可以具有多个有效的类在同一行。

This question几乎可以满足我的需求,但是它的多个类分别位于不同的行上。我需要将结果用分隔符(例如“,”)连接成字符串,以使输出的行数与输入的行数相同。

使用在这两个问题(12)中找到的想法,我能够提出一个解决方案,但是它需要一个普通的python for循环来遍历行,因此与完全使用熊猫的解决方案相比,我怀疑它会比较慢。

如果输入数据框使事情变得更容易,则可以使用实际的布尔值而不是整数编码。输出可以是一个数据帧或一系列数据;我最终将结果列添加到更大的数据框中。如果可以提供更好的解决方案,我也愿意使用numpy,但否则,我宁愿坚持使用pandas

解决方法

这是一个使用python列表理解来遍历每一行的解决方案:

import pandas as pd

def reverse_hot_encoding(df,sep=','):
    df = df.astype(bool)
    l = [sep.join(df.columns[row]) for _,row in df.iterrows()]
    return pd.Series(l)

if __name__ == '__main__':
    example_input = pd.DataFrame({"one"   : [0,1,0],"two"   : [0,"three" : [1,"four"  : [1,0]
                                  })
    print(reverse_hot_encoding(example_input))

这是输出:

0         three,four
1    one,three,four
2               three
3          one,three
4                    
dtype: object
,

您可以执行DataFrame.dot,这要比遍历数据帧中的所有行多faster

df.dot(df.columns + ',').str.rstrip(',')

0         three,three
4                    
dtype: object