Reemplazar valores de columna en un DataFrame de pandas

141

Estoy tratando de reemplazar los valores en una columna de un marco de datos. La columna ('femenino') solo contiene los valores 'femenino' y 'masculino'.

He probado lo siguiente:

w['female']['female']='1'
w['female']['male']='0' 

Pero reciba exactamente la misma copia de los resultados anteriores.

Idealmente, me gustaría obtener algo de salida que se asemeje al siguiente elemento de bucle.

if w['female'] =='female':
    w['female'] = '1';
else:
    w['female'] = '0';

He revisado la documentación de gotchas ( http://pandas.pydata.org/pandas-docs/stable/gotchas.html ) pero no puedo entender por qué no sucede nada.

Cualquier ayuda será apreciada.

Negro
fuente

Respuestas:

259

Si entiendo bien, quieres algo como esto:

w['female'] = w['female'].map({'female': 1, 'male': 0})

(Aquí convierto los valores a números en lugar de cadenas que contienen números. Puede convertirlos a "1"y "0", si realmente lo desea, pero no estoy seguro de por qué querría eso).

La razón por la que su código no funciona es porque el uso ['female']en una columna (la segunda 'female'en su w['female']['female']) no significa "seleccionar filas donde el valor es 'femenino'". Significa seleccionar filas donde el índice es 'femenino', de las cuales puede no haber ninguna en su DataFrame.

BrenBarn
fuente
66
Gracias. Exactamente lo que estaba buscando. Si tuviera que asignar 'hembra' a 1 y cualquier otra cosa a '0'. ¿Cómo funcionaría eso?
Negro
17
use esto solo si todos los valores de la columna se dan en la función de mapa. Los valores de columna no especificados en la función de mapa serán reemplazados por nan.
Chandra
1
También recomendaría usar la .locsintaxis para evitar SettingWithCopyWarning: pandas.pydata.org/pandas-docs/stable/…
NickBraunagel
2
en lugar de .map usé .replace
JS noob
¿Cómo me deshago del '.' de los miles en dos o más columnas, no pueden entenderlo. muchas gracias
M. Mariscal
115

Puede editar un subconjunto de un marco de datos utilizando loc:

df.loc[<row selection>, <column selection>]

En este caso:

w.loc[w.female != 'female', 'female'] = 0
w.loc[w.female == 'female', 'female'] = 1
Jimmy Petersson
fuente
1
¿Cómo lo adaptaría para que no necesite seleccionar filas específicas a través de una condición, solo todas las filas en una columna en particular? Por lo tanto, cambie todas las celdas de una columna a un valor particular.
Dhruv Ghulati
3
@DhruvGhulati, usaría df.loc [:, <selección de columna>]
40
w.female.replace(to_replace=dict(female=1, male=0), inplace=True)

Ver pandas.DataFrame.replace () docs .

jfs
fuente
Esta es la mejor solución para el problema que tengo, ¡gracias!
Andrew Brēza
38

Ligera variación:

w.female.replace(['male', 'female'], [1, 0], inplace=True)
deckard
fuente
19

Esto también debería funcionar:

w.female[w.female == 'female'] = 1 
w.female[w.female == 'male']   = 0
Nick Crawford
fuente
11

También se puede usar applycon .getie

w['female'] = w['female'].apply({'male':0, 'female':1}.get):

w = pd.DataFrame({'female':['female','male','female']})
print(w)

Marco de datos w:

   female
0  female
1    male
2  female

Utilizando applypara reemplazar valores del diccionario:

w['female'] = w['female'].apply({'male':0, 'female':1}.get)
print(w)

Resultado:

   female
0       1
1       0
2       1 

Nota: apply con el diccionario se debe usar si todos los valores posibles de las columnas en el marco de datos están definidos en el diccionario, de lo contrario, tendrá vacío para los que no están definidos en el diccionario.

estudiante
fuente
8

Esto es muy compacto:

w['female'][w['female'] == 'female']=1
w['female'][w['female'] == 'male']=0

Otra buena:

w['female'] = w['female'].replace(regex='female', value=1)
w['female'] = w['female'].replace(regex='male', value=0)
Azz
fuente
El primer ejemplo es la indexación encadenada y se advierte, ya que no puede garantizar si el df resultante es una copia o una vista. Ver indexación encadenada
Nordle
7

Alternativamente, existe la función incorporada pd.get_dummies para este tipo de tareas:

w['female'] = pd.get_dummies(w['female'],drop_first = True)

Esto le proporciona un marco de datos con dos columnas, una para cada valor que aparece en w ['hembra'], de las cuales suelta el primero (porque puede inferirlo de la que queda). La nueva columna se nombra automáticamente como la cadena que reemplazó.

Esto es especialmente útil si tiene variables categóricas con más de dos valores posibles. Esta función crea tantas variables ficticias necesarias para distinguir entre todos los casos. Tenga cuidado de no asignar todo el marco de datos a una sola columna, sino que si w ['mujer'] podría ser 'hombre', 'mujer' o 'neutral', haga algo como esto:

w = pd.concat([w, pd.get_dummies(w['female'], drop_first = True)], axis = 1])
w.drop('female', axis = 1, inplace = True)

Luego te quedan dos columnas nuevas que te dan la codificación ficticia de 'hembra' y te deshaces de la columna con las cadenas.

galliwuzz
fuente
4

Usando Series.mapconSeries.fillna

Si su columna contiene más cadenas que solo femaley male, Series.mapfallará en este caso ya que regresará NaNpara otros valores.

Es por eso que tenemos que encadenarlo con fillna:

Ejemplo por qué .mapfalla :

df = pd.DataFrame({'female':['male', 'female', 'female', 'male', 'other', 'other']})

   female
0    male
1  female
2  female
3    male
4   other
5   other
df['female'].map({'female': '1', 'male': '0'})

0      0
1      1
2      1
3      0
4    NaN
5    NaN
Name: female, dtype: object

Para el método correcto , encadenamos mapcon fillna, por lo que rellenamos NaNcon los valores de la columna original:

df['female'].map({'female': '1', 'male': '0'}).fillna(df['female'])

0        0
1        1
2        1
3        0
4    other
5    other
Name: female, dtype: object
Erfan
fuente
2

También hay una función pandasllamada factorizeque puede usar para realizar automáticamente este tipo de trabajo. Convierte las etiquetas a los números: ['male', 'female', 'male'] -> [0, 1, 0]. Vea esta respuesta para más información.

Roald
fuente
0

Creo que en respuesta debería señalarse qué tipo de objeto obtiene en todos los métodos sugeridos anteriormente: ¿es Serie o Marco de datos?

Cuando obtenga una columna por w.female.o w[[2]](donde, supongamos, 2 es el número de su columna), obtendrá DataFrame. Entonces, en este caso, puede usar métodos DataFrame como .replace.

Cuando usa .loco ilocrecupera Series, y Series no tienen .replacemétodo, por lo que debe usar métodos como apply, mapetc.

Alex-droid AD
fuente