将分类变量转换为基于单行频率的数字

6
这类似于scikit-learn中的LabelEncoder,但要求按照类别频率顺序进行数字值分配,即分配最高/最低(根据用例而定)数字的类别具有更高的出现频率。

例如,如果变量可以取值[a, b, c],并且具有以下频率:

  Category 
0        a 
0        a 
0        a 
0        a 
0        a 
1        b 
1        b 
1        b 
1        b 
1        b 
1        b 
1        b 
1        b 
1        b 
1        b 
2        c 
2        c 

a出现了5次,b出现了10次,c出现了2次。 然后我希望替换为b=1a=2c=3


如果两个值具有相同的频率,您希望发生什么? - DSM
3个回答

2

请参见argsort

df['Order'] = df['Frequency'].argsort() + 1
df

返回值

  Category  Frequency  Order
0        a          5      3
1        b         10      1
2        c          2      2

对不起,我误导了您,频率列不是数据的一部分。我会编辑这个表示。 - goelakash
1
@Alex,你还应该注意到你的结果与问题中显示的期望结果不符。频率5应该分配给2,而不是3。 - Warren Weckesser

1

如果您正在使用pandas,可以使用其map()方法

import pandas as pd
data = pd.DataFrame([['a'], ['b'], ['c']], columns=['category'])

print(data)

  category
0        a
1        b
2        c

mapping_dict = {'b':1, 'a':2, 'c':3}

print(data['category'].map(mapping_dict))

0    2
1    1
2    3

LabelEncoder使用np.unique查找列中存在的唯一值,返回按字母顺序排序的值,因此您无法在其中使用自定义排序。


嗨,Vivek,你的解决方案假设我事先知道数字标签。但是除非我看到频率并手动编写“mapping_dict”,否则我不会知道这一点。尽管如此,这不是我想要的。 - goelakash

1

根据@Vivek Kumar的建议,我使用了地图功能,使用排序列值的字典作为键,它们的位置作为值:

data.Category = data.Category.map(dict(zip(data.Category.value_counts().index, range(1, len(data.Category.value_counts().index)+1))))

看起来有点混乱,最好像这样分成几行:

sorted_indices = data.Category.value_counts().index
data.Category = data.Category.map(dict(zip(sorted_indices, range(1, len(sorted_indices)+1))))

这是我最接近需求的内容。输出看起来像这样:

    Category
0          2
1          2
2          2
3          2
4          2
5          1
6          1
7          1
8          1
9          1
10         1
11         1
12         1
13         1
14         1
15         3
16         3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接