2017-05-11 5 views
0

J'ai un fichier .csv avec des données dont je veux transformer certaines colonnes en un seul. Le problème se produit dans la deuxième dernière ligne, où l'index un-chaud (par exemple la première fonctionnalité) est placé dans toutes les lignes au lieu de celui dans lequel je suis actuellement. Il semble y avoir un problème avec la façon dont j'accède à la liste 2D ... des suggestions? merciun codage à chaud, éléments de la liste d'accès

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 
+0

Il y a encore une erreur tiret après la première instruction 'if'. – strubbly

+0

Bonjour, si une réponse a déjà trouvé réponse à votre question, merci de considérer [l'accepter] (https://meta.stackexchange.com/q/5234/179419) en cochant la case à cocher qui lui est adjacente. Ceci indique à la communauté plus large que vous avez trouvé une solution et donne une certaine réputation à la fois le répondeur et vous-même. Il n'y a aucune obligation de le faire. – Lafexlos

+0

J'ai enlevé le mot "(résolu)" du titre de la question. (La plupart des futurs utilisateurs qui ont des problèmes ne vont pas chercher leur problème en utilisant un terme de "résolu"). La bonne façon de dire que votre problème est résolu est d'accepter l'une des réponses - voir le lien dans le commentaire de Lafexlos. – YowE3K

Répondre

0

Votre problème vient de l'objet vector que vous créez à l'encodage d'un chaud; vous avez créé un objet, puis créé un one_hot_list contenant 1460 références au même objet. Lorsque vous effectuez un changement dans l'une des lignes, il sera reflété dans toutes les lignes.

solution rapide serait de créer des copies séparées de la vector pour chaque ligne (voir How to clone or copy a list?):

one_hot_list.append(vector[:]) 

Certaines des autres choses que vous faites dans votre fonction sont un peu lent ou rond-point. Je vous suggère quelques changements:

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 

Ce builds different_elements dans le temps linéaire en utilisant le type de données set et utilise compréhensions de liste pour produire les valeurs pour one_hot_list[0] (la liste des valeurs des éléments qui sont un chaud codé), le zéro vector et one_hot_list[1:] (qui est la valeur réelle de la matrice codée à chaud). En outre, il existe un dict appelé index_lookup qui vous permet de mapper rapidement les valeurs d'éléments sur leur index entier, au lieu de les rechercher encore et encore. Enfin, votre index de ligne dans la matrice one_hot_list peut être géré pour vous par enumerate.

+0

merci pour les conseils supplémentaires –

0

Je ne suis pas 100% sûr de ce que vous essayez de faire, mais le problème que vous voyez est dans ces lignes:

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

Ces créent les one_hot_list que 1460 références au même vecteur de zéros . Alors que je pense que vous voulez que ce soit un nouveau vecteur à chaque fois. Une solution directe serait juste de le copier à chaque fois:

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

Mais une approche plus Pythonic serait de créer la liste avec une compréhension. Peut-être quelque chose comme ceci:

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

merci, c'est ça :) –

0

vous pouvez utiliser set() pour compter les éléments uniques dans la liste

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

'different_elements' garde juste la trace des valeurs d'une colonne spécifique, pas la ligne entière. Vous voulez 'different_elements = list (set (row [colonne] pour row dans data [1:]))'. – wildwilhelm

+0

oui, vous avez raison – Tobias

0

je vous suggère de vous épargner les tracas de re-mettre en œuvre ce en Python ordinaire.Vous pouvez utiliser l'utilisation pandas.get_dummies pour cela:

Tout d'abord quelques données de test (test.csv):

A 
Foo 
Bar 
Baz 

Puis en Python:

import pandas as pd 

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

table

Vous pouvez récupérer le tableau numpy sous-jacente utilisant:

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

qui se traduit par:

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