Python – Diccionario de archivo CSV con múltiples valores por clave

Estoy tratando de hacer un diccionario desde un archivo csv en python. Digamos que el CSV contiene:

Student food amount John apple 15 John banana 20 John orange 1 John grape 3 Ben apple 2 Ben orange 4 Ben strawberry 8 Andrew apple 10 Andrew watermelon 3 

Lo que estoy imaginando es un diccionario cuya clave será el nombre del estudiante y una lista como el valor donde cada entrada corresponde a un alimento diferente. Tendría que contar el número de alimentos únicos en la segunda columna y esa sería la longitud del vector. Por ejemplo:

 The value of [15,20,1,3,0,0] would correspond to [apple, banana, orange, grape, strawberry, watermelon] for 'John'. The value of [2,0,4,0,8,0] would correspond to [apple, banana, orange, grape, strawberry, watermelon] for 'Ben'. The value of [10,0,0,0,0,3] would correspond to [apple, banana, orange, grape, strawberry, watermelon] for 'Andrew' 

La salida esperada del dict se vería así:

 dict={'John':{[15,20,1,3,0,0]}, 'Ben': {[2,0,4,0,8,0]}, 'Andrew': {[10,0,0,0,0,3]}} 

Para empezar, tengo problemas para crear el diccionario o si un diccionario es el enfoque correcto. Lo que tengo que empezar con:

 import csv data_file=open('data.csv','rU') reader=csv.DictReader(data_file) data={} for row in reader: data[row['Student']]=row data_file.close() 

Gracias por tomarse el tiempo para leer. Cualquier ayuda sería muy apreciada.

Related of "Python – Diccionario de archivo CSV con múltiples valores por clave"

Aquí hay una versión que usa el diccionario regular. Sin embargo, el valor predeterminado es definitivamente mejor.

 import csv data_file=open('data.csv','rU') reader=csv.DictReader(data_file) data={} for row in reader: if row['Student'] in data: data[row['Student']].append(row['amount']) else: data[row['Student']] = [row['amount']] data_file.close() 

EDITAR:

 For matching indicies import csv from collections import defaultdict data_file=open('data.csv','rU') reader=csv.DictReader(data_file) data=defaultdict(lambda:[0,0,0,0]) fruit_to_index = defaultdict(lambda:None,{'apple':0,'banana':1,'orange':2,'grape':3}) for row in reader: if fruit_to_index[row['food']] != None: data[row['Student']][fruit_to_index[row['food']]] = int(row['amount']) data_file.close() 

print data serían

 defaultdict( at address>, {'John': [15, 20, 1, 3], 'Ben': [2 , 0 , 0, 0], 'Andrew': [10, 0 , 0, 0]}) 

Creo que esto es lo que quieres.

EDIT2: Hizo esto cuando la lista de frutas no incluía fresa y sandía, pero debería ser muy fácil de agregar. Si la lista es demasiado grande

Generar la fruta para indexar el mapeo.

 set_of_fruits = set() for row in reader: set_of_fruits.add(row['food']) c = 0 for e in set_of_fruits: fruit_to_index[e] = c c += 1 

Tenga en cuenta que el orden de set_of_fruits no se genera.

data = defaultdict(lambda:[0,0,0,0]) convierte en

data = defaultdict(lambda:[0 for x in range(len(set_of_fruits))])

Intenta esto, creo que esto es lo que quieres. Observe el uso de defaultdict , se podría hacer con un diccionario regular, pero defaultdict es muy útil en estos casos:

 import csv from collections import defaultdict data=defaultdict(list) with open('data.csv','rb') as data_file: reader=csv.DictReader(data_file) for row in reader: data[row['Student']].append(row['amount']) 

Probablemente quieras una estructura de diccionario anidada; mantener una lista y luego tratar de hacer coincidir los índices con los nombres de los alimentos se volverá velludo.

 import csv from collections import defaultdict data = defaultdict(dict) with open('data.csv', 'r') as file: reader = csv.DictReader(file) for row in reader: data[row['Student']][row['food']] = row['amount'] 

Esto te dará una estructura así:

 {'John': {'apple': 15, 'banana': 20, 'orange': 1}, 'Ben': {'apple': 2, 'watermelon': 4}, #etc. } 

Eso le permite buscar alimentos en particular sin tener que intentar hacer una referencia cruzada a otra lista para averiguar dónde encontrar los conteos, y admite cualquier cantidad de alimentos sin tener que llenar sus listas con ceros para todos los que faltan.

Si desea ser extravagante, puede usar un código defaultdict nested, de modo que buscar alimentos que no se KeyError introducido devolverá los ceros automáticamente, en lugar de dar a KeyError s; solo cambia la segunda línea a:

 data = defaultdict(lambda: defaultdict(int)) 

Utilice el método setdefault del dict.

 import csv data_file=open('data.csv','rU') reader=csv.DictReader(data_file) data={} for row in reader: data.setdefault(row['Student'], []).append(row['amount']) data_file.close() 

Si la clave, por ejemplo. “John”, no existe, lo crea con el valor predeterminado proporcionado. En este caso, una lista vacía es la predeterminada.