one-hot编码,访问列表元素

one-hot encoding, access list elements

我有一个 .csv 文件,其中包含我想将其中一些列转换为单列的数据。问题出现在倒数第二行,其中单热索引(例如第一个特征)被放置在所有行中,而不仅仅是我当前所在的行。 我如何访问 2D 列表似乎有些问题...有什么建议吗? 谢谢

def one_hot_encode(data_list, column):
    one_hot_list = [[]]
    different_elements = []

    for row in data_list[1:]:                  # count different elements
        if row[column] not in different_elements:
            different_elements.append(row[column])

    for i in range(len(different_elements)):   # set variable names
        one_hot_list[0].append(different_elements[i])

    vector = []                              # create list shape with zeroes
    for i in range(len(different_elements)):
        vector.append(0)
    for i in range(1460):
        one_hot_list.append(vector)

    ind_row = 1                                # encode 1 for each sample
    for row in data_list[1:]:
        index = different_elements.index(row[column])
        one_hot_list[ind_row][index] = 1     # mistake!! sets all rows to 1
        ind_row += 1

您的问题源于您为执行一次性编码而创建的 vector 对象;您已经创建了一个对象,然后构建了一个包含 1460 个对同一对象的引用的 one_hot_list。当您在其中一行中进行更改时,它会反映在所有行中。

快速解决方案是为每一行创建单独的 vector 副本(参见 How to clone or copy a list?):

one_hot_list.append(vector[:])

你在你的函数中做的其他一些事情有点慢或迂回。我建议进行一些更改:

def one_hot_encode(data_list, column):
    one_hot_list = [[]]

    # count different elements
    different_elements = set(row[column] for row in data_list[1:])

    # convert different_elements to a list with a canonical order,
    # store in the first element of one_hot_list
    one_hot_list[0] = sorted(different_elements)

    vector = [0] * len(different_elements)   # create list shape with zeroes
    one_hot_list.extend([vector[:] for _ in range(1460)])

    # build a mapping of different_element values to indices into
    # one_hot_list[0]
    index_lookup = dict((e,i) for (i,e) in enumerate(one_hot_list[0]))
    # encode 1 for each sample
    for rindex, row in enumerate(data_list[1:], 1):
        cindex = index_lookup[row[column]]
        one_hot_list[rindex][cindex] = 1

这通过使用 set 数据类型在线性时间内构建 different_elements,并使用列表理解生成 one_hot_list[0] 的值(元素值列表是一个-热编码),零 vectorone_hot_list[1:](这是实际的单热编码矩阵值)。此外,还有一个名为 index_lookupdict 可让您快速将元素值映射到它们的整数索引,而不是一遍又一遍地搜索它们。最后,one_hot_list 矩阵中的行索引可以由 enumerate.

为您管理

我不是 100% 确定你想做什么,但你看到的问题是在这些行中:

for i in range(1460):
    one_hot_list.append(vector)

这些正在创建 one_hot_list 作为对同一零向量的 1460 个引用。而我认为你每次都希望它成为一个新的向量。一个直接的解决方法就是每次都复制它:

for i in range(1460):
    one_hot_list.append(vector[:])

但更 Pythonic 的方法是创建具有理解力的列表。也许是这样的:

vector_size = len(different_elements):
one_hot_list = [ [0] * vector_size for i in range(1460)]

您可以使用 set() 来计算列表中的唯一项目

 different_elements = list(set(data[1:]))

我建议您避免在简单的 Python 中重新实现它的麻烦。您可以为此使用 pandas.get_dummies

首先是一些测试数据(test.csv):

A
Foo
Bar
Baz

然后在 Python:

import pandas as pd

df = pd.read_csv('test.csv')
# convert column 'A' to one-hot encoding
pd.get_dummies(df['A'])

您可以使用以下方法检索基础 numpy 数组:

pd.get_dummies(df['A']).values

这导致:

array([[0, 0, 1],
       [1, 0, 0],
       [0, 1, 0]], dtype=uint8)