在字典上使用标签编码器

Using label encoder on a dictionary

我正在使用 sklearn LabelEncoder。我知道如何将它用于一维数组,但我的用例是这样的:

我有多个这样的字典数组(这实际上是我在分类器中分配每个文本标签 u'a'u'b' 等的成本),都在一个字典中:

{'open_model':    
[
    {u'a': 47502.125, u'c': 45.3, u'd': 2.3, u'e': 0.45},
    {u'b': 121, u'a': 1580.5625, u'c': 12, u'e': 62,u'd':0.343},
    {u'e': 12321, u'b': 4, u'a': 0.1112}
    ],
 'closed_model':
 [
    {u'a': 1231.22, u'c': 43.1},
    {u'b': 342.2, u'a': 121.1, u'c': 343},
    {u'b': 14.2, u'a': 53.2}
    ]
}

我需要能够将其编码为数字标签,然后将它们全部解码回来,例如:

[
    {1: 47502.125, 3: 45.3, 4: 2.3, 5: 0.45},
    {2: 121, 1: 1580.5625, 3: 12, 5: 62, 4: 0.343},
    {5: 12321, 2: 4, 1: 0.1112}
    ]

我有效地使用它来为每一行生成最佳标签的预测,所以:

[5, 4, 1] perhaps in this case.

我需要做的是能够将其解码回:

[u'e',u'd', u'a'] perhaps in this case.

我怎样才能获得相同的 LabelEncoder 功能,但要 fit_transform 一个字典数组,其中字典键是我的标签?

注意,dict 数组中的 dict 长度不同,但我确实有所有潜在标签的列表,即对于 open_model 标签,set([u'a',u'b',u'c',u'd',u'e']) 和 closed_model标签:set([u'a',u'b',u'c']).

看来你总是有'a'、'b'、'c'、'd'、'e'。如果是这种情况,为什么不使用 pandas 数据框而忘记编码器呢?您有点需要重写您使用的词典的键,所以无论如何都会很乱!

import pandas as pd
i = [
{u'a': 47502.125, u'b': 1580.5625, u'c': 45.3, u'd': 2.3, u'e': 0.45},
{u'b': 121, u'a': 1580.5625, u'c': 12, u'e': 62, u'd': 0.343},
{u'e': 12321, u'b': 4, u'd': 5434, u'c': 2.3, u'a': 0.1112}
]
# transform to data frame
df = pd.DataFrame(i)
print df
            a          b     c         d         e
0  47502.1250  1580.5625  45.3     2.300      0.45
1   1580.5625   121.0000  12.0     0.343     62.00
2      0.1112     4.0000   2.3  5434.000  12321.00

# create a mapping between columns and encoders
mapping = dict((k, v) for k, v in enumerate(df.columns))

# rename columns
df.columns = range(len(df.columns))

# print your new input data
print df.to_dict(orient='records)
[{0: 47502.125, 1: 1580.5625, 2: 45.3, 3: 2.3, 4: 0.45},
 {0: 1580.5625, 1: 121.0, 2: 12.0, 3: 0.343, 4: 62.0},
 {0: 0.1112, 1: 4.0, 2: 2.3, 3: 5434.0, 4: 12321.0}]

# translate prediction
prediction = [3, 4, 1]
print [mapping[k] for k in prediction]
[u'd', u'e', u'b']

这不是直截了当的,但我想它会比使用编码器花费更少的时间:)

尽管使用已实现的功能是一种很好的做法,但您可以使用几行代码轻松实现。鉴于您的列表输入:

dico = [
{u'a': 47502.125, u'b': 1580.5625, u'c': 45.3, u'd': 2.3, u'e': 0.45},
{u'b': 121, u'a': 1580.5625, u'c': 12, u'e': 62, u'd': 0.343},
{u'e': 12321, u'b': 4, u'd': 5434, u'c': 2.3, u'a': 0.1112}
]

您可以通过以下方式简单地获取标签集:

keyset = set(dico[0].keys()) #Get the set of keys assuming they all appear in each list item. 
mapping = { val:key+1 for key,val in enumerate(list(keyset))} # Create a mapping from int -> str
inv_mapping = { key+1:val for key,val in enumerate(list(keyset))} # Create a mapping from str:int. 

有了 mappinginv_mapping,您可以通过以下方式更改数据的表示形式:

for inner_dict in dico:
    for key in inner_dict.keys():
        inner_dict[mapping[key]] = inner_dict.pop(key)
print dico

这会给你 [{1: 47502.125, ...}] 然后如果需要的话:

for inner_dict in dico:
    for key in inner_dict.keys():
        inner_dict[inv_mapping[key]] = inner_dict.pop(key)
print dico

获取初始版本。

此外,也许与您的问题更密切相关,有了您的输出 [5, 4, 1] 您可以通过以下方式轻松转换它:

print [inv_mapping[i] for i in x]