Declaración del problema Quiero ir desde este dataframe que es básicamente un codificado en caliente.
In [2]: pd.DataFrame({"monkey":[0,1,0],"rabbit":[1,0,0],"fox":[0,0,1]}) Out[2]: fox monkey rabbit 0 0 0 1 1 0 1 0 2 1 0 0 3 0 0 0 4 0 0 0
A este que está ‘inverso’ codificado en caliente.
In [3]: pd.DataFrame({"animal":["monkey","rabbit","fox"]}) Out[3]: animal 0 monkey 1 rabbit 2 fox
Me imagino que hay algún tipo de uso inteligente de aplicar o zip para hacer cosas delgadas, pero no estoy seguro de cómo … ¿Puede alguien ayudarme?
No he tenido mucho éxito con la indexación, etc., para tratar de resolver este problema.
Yo usaría aplicar para decodificar las columnas:
In [2]: animals = pd.DataFrame({"monkey":[0,1,0,0,0],"rabbit":[1,0,0,0,0],"fox":[0,0,1,0,0]}) In [3]: def get_animal(row): ...: for c in animals.columns: ...: if row[c]==1: ...: return c In [4]: animals.apply(get_animal, axis=1) Out[4]: 0 rabbit 1 monkey 2 fox 3 None 4 None dtype: object
ACTUALIZACIÓN: creo que ayhan tiene razón y debería ser:
df.idxmax(axis=1)
Manifestación:
In [40]: s = pd.Series(['dog', 'cat', 'dog', 'bird', 'fox', 'dog']) In [41]: s Out[41]: 0 dog 1 cat 2 dog 3 bird 4 fox 5 dog dtype: object In [42]: pd.get_dummies(s) Out[42]: bird cat dog fox 0 0.0 0.0 1.0 0.0 1 0.0 1.0 0.0 0.0 2 0.0 0.0 1.0 0.0 3 1.0 0.0 0.0 0.0 4 0.0 0.0 0.0 1.0 5 0.0 0.0 1.0 0.0 In [43]: pd.get_dummies(s).idxmax(1) Out[43]: 0 dog 1 cat 2 dog 3 bird 4 fox 5 dog dtype: object
Respuesta VIEJA: (muy probablemente, respuesta incorrecta)
prueba esto:
In [504]: df.idxmax().reset_index().rename(columns={'index':'animal', 0:'idx'}) Out[504]: animal idx 0 fox 2 1 monkey 1 2 rabbit 0
datos:
In [505]: df Out[505]: fox monkey rabbit 0 0 0 1 1 0 1 0 2 1 0 0 3 0 0 0 4 0 0 0
Prueba esto:
df = pd.DataFrame({"monkey":[0,1,0,1,0],"rabbit":[1,0,0,0,0],"fox":[0,0,1,0,0], "cat":[0,0,0,0,1]}) df cat fox monkey rabbit 0 0 0 0 1 1 0 0 1 0 2 0 1 0 0 3 0 0 1 0 4 1 0 0 0 pd.DataFrame([x for x in np.where(df ==1, df.columns,'').flatten().tolist() if len(x) >0],columns= (["animal"]) ) animal 0 rabbit 1 monkey 2 fox 3 monkey 4 cat
Lo haría:
cols = df.columns.to_series().values pd.DataFrame(np.repeat(cols[None, :], len(df), 0)[df.astype(bool).values], df.index[df.any(1)])
El método de MaxU tiene ventaja para grandes marcos de datos
df
pequeño 5 x 3
df
grande 1000000 x 52
Esto funciona con tags únicas y múltiples.
Podemos utilizar la indexación avanzada para abordar este problema. Aquí está el enlace.
import pandas as pd df = pd.DataFrame({"monkey":[1,1,0,1,0],"rabbit":[1,1,1,1,0],\ "fox":[1,0,1,0,0], "cat":[0,0,0,0,1]}) df['tags']='' # to create an empty column for col_name in df.columns: df.ix[df[col_name]==1,'tags']= df['tags']+' '+col_name print df
Y el resultado es:
cat fox monkey rabbit tags 0 0 1 1 1 fox monkey rabbit 1 0 0 1 1 monkey rabbit 2 0 1 0 1 fox rabbit 3 0 0 1 1 monkey rabbit 4 1 0 0 0 cat
Explicación: iteramos sobre las columnas en el dataframe.
df.ix[selection criteria, columns to write value] = value df.ix[df[col_name]==1,'tags']= df['tags']+' '+col_name
La línea anterior básicamente encuentra todos los lugares donde df [nombre_col] == 1, selecciona las ‘tags’ de la columna y lo configura en el valor RHS que es df [‘tags’] + ” + nombre_col
Nota: .ix
ha quedado en desuso desde Pandas v0.20. En su lugar, debe utilizar .loc
o .iloc
, según corresponda.