web-dev-qa-db-fra.com

Remplacement conditionnel Pandas

Je fais probablement quelque chose de très stupide, mais je suis perplexe.

J'ai un cadre de données et je souhaite remplacer les valeurs d'une colonne donnée dépassant une valeur égale à zéro. J'avais pensé que c'était un moyen d'y parvenir:

df[df.my_channel > 20000].my_channel = 0

Si je copie le canal dans un nouveau cadre de données, c'est simple:

df2 = df.my_channel 

df2[df2 > 20000] = 0

cela fait exactement ce que je veux, mais ne semble pas fonctionner avec le canal dans le cadre de données d'origine.

89
BMichell

.ix indexeur fonctionne correctement pour pandas version antérieure à 0.20.0, mais depuis pandas 0.20.0, l'indicateur .ix est obsolète , vous devriez donc éviter de l'utiliser. A la place, vous pouvez utiliser les indexeurs .loc ou iloc. Vous pouvez résoudre ce problème en:

mask = df.my_channel > 20000
column_name = 'my_channel'
df.loc[mask, column_name] = 0

Ou, en une ligne,

df.loc[df.my_channel > 20000, 'my_channel'] = 0

mask vous aide à sélectionner les lignes dans lesquelles df.my_channel > 20000 est True, tandis que df.loc[mask, column_name] = 0 définit la valeur 0 sur les lignes sélectionnées où mask est dans la colonne dont le nom est column_name.

Mise à jour: Dans ce cas, vous devez utiliser loc car si vous utilisez iloc, vous obtiendrez un NotImplementedError vous indiquant que iLocation L'indexation booléenne basée sur un type entier n'est pas disponible .

130
lmiguelvargasf

Essayer

df.loc[df.my_channel > 20000, 'my_channel'] = 0

Remarque: Depuis la v0.20.0, ixest obsolète en faveur de loc/iloc.

68
lowtech

La fonction np.where fonctionne comme suit:

df['X'] = np.where(df['Y']>=50, 'yes', 'no')

Dans votre cas, vous voudriez:

import numpy as np
df['my_channel'] = np.where(df.my_channel > 20000, 0, df.my_channel)
20
seeiespi

La raison pour laquelle votre image de données d'origine ne met pas à jour est parce que indexé en chaîne peut vous amener à modifier une copie plutôt qu'une vue de votre image de données. Les docs donnent ce conseil:

Lorsque vous définissez des valeurs dans un objet pandas, vous devez éviter ce que l'on appelle l'indexation chaînée.

Vous avez quelques alternatives: -

loc + indexation booléenne

loc peut être utilisé pour définir des valeurs et prend en charge les masques booléens:

_df.loc[df['my_channel'] > 20000, 'my_channel'] = 0
_

mask + indexation booléenne

Vous pouvez affecter à votre série:

_df['my_channel'] = df['my_channel'].mask(df['my_channel'] > 20000, 0)
_

Ou vous pouvez mettre à jour votre série sur place:

_df['my_channel'].mask(df['my_channel'] > 20000, 0, inplace=True)
_

np.where + indexation booléenne

Vous pouvez utiliser NumPy en attribuant votre série d'origine lorsque votre condition est et non satisfait; Cependant, les deux premières solutions sont plus propres puisqu'elles ne modifient explicitement que les valeurs spécifiées.

_df['my_channel'] = np.where(df['my_channel'] > 20000, 0, df['my_channel'])
_
11
jpp

Essaye ça:

df.my_channel = df.my_channel.where(df.my_channel <= 20000, other= 0)

ou

df.my_channel = df.my_channel.mask(df.my_channel > 20000, other= 0)

0
R. Shams

J'utiliserais la fonction lambda sur un Series d'un DataFrame comme ceci:

f = lambda x: 0 if x>100 else 1
df['my_column'] = df['my_column'].map(f)

Je n’affirme pas que c’est un moyen efficace, mais cela fonctionne bien.

0
cyber-math