将字符串列表转换为 Python 中的类别整数

Convert a list of string to category integer in Python

给定一个字符串列表,

['a', 'a', 'c', 'a', 'a', 'a', 'd', 'c', 'd', 'd', 'd', 'd', 'c', 'd', 'd', 'd', 'd', 'c', 'd', 'd', 'd', 'd', 'c', 'b', 'b', 'b', 'd', 'b', 'b', 'b']

我想转换成整数类别形式

[0, 0, 2, 0, 0, 0, 3, 2, 3, 3, 3, 3, 2, 3, 3, 3, 3, 2, 3, 3, 3, 3, 2, 1, 1, 1, 3, 1, 1, 1]

这可以使用 numpy unique 实现,如下所示

ipt=['a', 'a', 'c', 'a', 'a', 'a', 'd', 'c', 'd', 'd', 'd', 'd', 'c', 'd', 'd', 'd', 'd', 'c', 'd', 'd', 'd', 'd', 'c', 'b', 'b', 'b', 'd', 'b', 'b', 'b']
_, opt = np.unique(np.array(ipt), return_inverse=True)

但是,我很好奇是否有另一种不需要导入的替代方法 numpy

你可以从函数式编程书上做个笔记:

ipt=['a', 'a', 'c', 'a', 'a', 'a', 'd', 'c', 'd', 'd', 'd', 'd', 'c', 'd', 'd', 'd', 'd', 'c', 'd', 'd', 'd', 'd', 'c', 'b', 'b', 'b', 'd', 'b', 'b', 'b']
opt = list(map(lambda x: ord(x)-97, ipt))

此代码遍历输入数组并将每个元素传递给 lambda 函数,该函数采用字符的 ascii 值,然后减去 97(将字符转换为 0-25)。

如果每个字符串不是单个字符,则可能需要调整 lambda 函数。

如果您只对查找因子的整数表示感兴趣,那么在使用 set 查找唯一值后,您可以使用字典理解和 enumerate 来存储映射:

lst = ['a', 'a', 'c', 'a', 'a', 'a', 'd', 'c', 'd', 'd', 'd', 'd', 'c', 'd', 'd', 'd', 'd', 'c', 'd', 'd', 'd', 'd', 'c', 'b', 'b', 'b', 'd', 'b', 'b', 'b']

d = {x: i for i, x in enumerate(set(lst))}
lst_new = [d[x] for x in lst]
print(lst_new)

# [3, 3, 0, 3, 3, 3, 2, 0, 2, 2, 2, 2, 0, 2, 2, 2, 2, 0, 2, 2, 2, 2, 0, 1, 1, 1, 2, 1, 1, 1]

这种方法可以用于一般因素,即因素不一定是'a''b'等,但可以是'dog''bus', 等。一个缺点是它不关心因素的顺序。如果您希望表示保留顺序,可以使用 sorted:

d = {x: i for i, x in enumerate(sorted(set(lst)))}
lst_new = [d[x] for x in lst]
print(lst_new)

# [0, 0, 2, 0, 0, 0, 3, 2, 3, 3, 3, 3, 2, 3, 3, 3, 3, 2, 3, 3, 3, 3, 2, 1, 1, 1, 3, 1, 1, 1]

您可以编写一个自定义函数来执行与您使用 numpy.unique() 相同的操作。

def unique(my_list):
    ''' Takes a list and returns two lists, a list of each unique entry and the index of
    each unique entry in the original list
    '''
    unique_list = []
    int_cat = []
    for item in my_list:
        if item not in unique_list:
            unique_list.append(item)
        int_cat.append(unique_list.index(item))
    return unique_list, int_cat

或者,如果您希望对索引进行排序。

def unique_ordered(my_list):
    ''' Takes a list and returns two lists, an ordered list of each unique entry and the
    index of each unique entry in the original list
    '''
    # Unique list
    unique_list = []
    for item in my_list:
        if item not in unique_list:
            unique_list.append(item)

    # Sorting unique list alphabetically
    unique_list.sort()

    # Integer category list
    int_cat = []
    for item in my_list:
        int_cat.append(unique_list.index(item))
    return unique_list, int_cat

将这两个的计算时间与 numpy.unique() 的示例列表的 100,000 次迭代进行比较,我们得到:

numpy = 2.236004s
unique = 0.460719s
unique_ordered = 0.505591s

显示对于简单列表,任一选项都比 numpty 更快。更复杂的字符串使 unique()unique_ordered 的速度下降比 numpy.unique() 大得多。对包含 20 个字符串的 100 个元素的随机列表进行 10,000 次迭代,我们得到以下时间:

numpy = 0.45465s
unique = 1.56963s
unique_ordered = 1.59445s

因此,如果效率很重要并且您的列表中有更多 complex/a 种类繁多的字符串,那么使用 numpy.unique()

可能会更好