Tengo un marco de datos y un diccionario. Necesito agregar una nueva columna al marco de datos y calcular sus valores en función del diccionario.
Aprendizaje automático, agregando nuevas características basadas en alguna tabla:
score = {(1, 45, 1, 1) : 4, (0, 1, 2, 1) : 5}
df = pd.DataFrame(data = {
'gender' : [1, 1, 0, 1, 1, 0, 0, 0, 1, 0],
'age' : [13, 45, 1, 45, 15, 16, 16, 16, 15, 15],
'cholesterol' : [1, 2, 2, 1, 1, 1, 1, 1, 1, 1],
'smoke' : [0, 0, 1, 1, 7, 8, 3, 4, 4, 2]},
dtype = np.int64)
print(df, '\n')
df['score'] = 0
df.score = score[(df.gender, df.age, df.cholesterol, df.smoke)]
print(df)
Espero el siguiente resultado:
gender age cholesterol smoke score
0 1 13 1 0 0
1 1 45 2 0 0
2 0 1 2 1 5
3 1 45 1 1 4
4 1 15 1 7 0
5 0 16 1 8 0
6 0 16 1 3 0
7 0 16 1 4 0
8 1 15 1 4 0
9 0 15 1 2 0
python
pandas
dataframe
dictionary
Mikola
fuente
fuente

MultiIIndex. Alternativa:df['score'] =df.set_index(['gender', 'age', 'cholesterol', 'smoke']).index.map(score).fillna(0).to_numpy().dfvíaset_index, un nuevoSeriesconstructor de vías. Aunque obtiene un beneficio de la alineación del índice cuando se lo asignadf['score']. Por último,fillna(0, downcast='infer')hace el trabajo, pero nadie debería preferir esta larga solución con la creación de muchos objetos pandas innecesariamente.mergepodría lograr. Pensé que esa respuesta se publicaría rápidamente, así que opté por una alternativa y, por alguna razón, tenía MultiIndices en mi mente. Estoy de acuerdo, esta probablemente no debería ser la respuesta aceptada, así que espero que eso no suceda.Utilizando
assignuna comprensión de lista, obteniendo una tupla de valores (cada fila) delscorediccionario, por defecto a cero si no se encuentra.Tiempos
Dada la variedad de enfoques, pensé que sería interesante comparar algunos de los tiempos.
fuente
score.get, usaríaitertuplesozip(*map(df.get, df))... Para reiterar, este es mi enfoque preferido.df.assign(score=[score.get(t, 0) for t in zip(*map(df.get, df))])1.0es el mismo que el hash, por1lo que las búsquedas de tuplas deberían dar como resultado la misma respuesta. Disculpas @Alexander por tantos comentarios sobre esto, pero solo quiero que las personas voten más por esto porque ... deberían (-:.valueses carozip(*map(df.get, ['col2', 'col1', 'col5']))u obtener tuplas de una modificación dedf:zip(*map(df.eq(1).get, df))Podrías usar map , ya que score es un diccionario:
Salida
Como alternativa, podría utilizar una lista de comprensión:
fuente
Lista de comprensión y mapa:
Salida:
fuente
reindexO
mergefuente
Puede ser otra forma estaría usando
.loc[]:fuente
Solución simple de una línea, uso
getytuplefila-sabio,La solución anterior supone que no hay columnas distintas de las deseadas en orden. Si no, solo use columnas
fuente
score.getes bueno. Sin embargo, debería preferir una comprensión, en mi opinión. Ver los horarios de @ Alexander .