Горячее кодирование, элементы списка доступа
У меня есть файл.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
4 ответа
Ваша проблема проистекает из vector
объект, который вы создаете для выполнения горячего кодирования; Вы создали один объект, а затем создали one_hot_list
который содержит 1460 ссылок на один и тот же объект. Когда вы сделаете изменение в одной из строк, оно будет отражено во всех строках.
Быстрое решение было бы создать отдельные копии vector
для каждой строки (см. Как клонировать или скопировать список?):
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
Это строит different_elements
в линейном времени с помощью set
тип данных, и использует списки для получения значений для one_hot_list[0]
(список значений элементов, которые подвергаются горячему кодированию), ноль vector
, а также one_hot_list[1:]
(которое является фактическим значением матрицы с горячим кодированием). Кроме того, есть dict
называется index_lookup
это позволяет вам быстро отображать значения элементов в их целочисленный индекс, а не искать их снова и снова. Наконец, ваш индекс строки в one_hot_list
матрица может управляться для вас enumerate
,
Вы можете использовать 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)
Я не уверен на 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)]