【问题标题】:one-hot encoding, access list elementsone-hot 编码,访问列表元素
【发布时间】:2017-10-10 07:53:49
【问题描述】:

我有一个 .csv 文件,其中包含我想将其中一些列转换为 one-hot 的数据。问题出现在倒数第二行,其中单热索引(例如第一个特征)被放置在所有行中,而不仅仅是我当前所在的行。 我如何访问 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

【问题讨论】:

  • 在第一个if 语句之后还有一个缩进错误。
  • 您好,如果以下任何答案解决了您的问题,请点击旁边的复选标记考虑accepting it。这向更广泛的社区表明您已经找到了解决方案,并为回答者和您自己提供了一些声誉。没有义务这样做。
  • 我从问题标题中删除了“(已解决)”一词。 (大多数有问题的未来用户不会使用“已解决”一词来搜索他们的问题)。表示您的问题已解决的正确方法是接受其中一个答案 - 请参阅 Lafexlos 评论中的链接。

标签: python arrays list one-hot-encoding


【解决方案1】:

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

快速解决方案是为每一行创建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] 的值(被一次性编码的元素值列表),零@ 987654330@ 和 one_hot_list[1:](这是实际的 one-hot-encoded 矩阵值)。此外,还有一个名为index_lookup 的dict 可以让您快速将元素值映射到它们的整数索引上,而不是一遍又一遍地搜索它们。最后,one_hot_list 矩阵中的行索引可以由enumerate 为您管理。

【讨论】:

    【解决方案2】:

    我不能 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)]
    

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

      • different_elements 只跟踪特定列的值,而不是整行。你想要different_elements = list(set(row[column] for row in data[1:]))。
      【解决方案4】:

      我建议您免去用普通 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)
      

      【讨论】:

        猜你喜欢
        • 2018-01-29
        • 2018-05-22
        • 2018-03-29
        • 1970-01-01
        • 2017-10-23
        • 2017-06-21
        • 2021-04-14
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多