web-dev-qa-db-fra.com

Mettre à jour les valeurs de ligne où certaines conditions sont remplies dans pandas

Disons que j'ai le dataframe suivant:

table

Quel est le moyen le plus efficace de mettre à jour les valeurs des colonnes feat et another_feat où le flux est un nombre 2 ?

Est-ce ceci?

for index, row in df.iterrows():
    if df1.loc[index,'stream'] == 2:
       # do something

UPDATE: Que faire si j'ai plus de 100 colonnes? Je ne veux pas nommer explicitement les colonnes que je veux mettre à jour. Je veux diviser la valeur de chaque colonne par 2 (sauf pour la colonne de flux).

Donc, pour être clair quel est mon objectif:

Division de toutes les valeurs par 2 sur toutes les lignes du flux 2, mais modification de la colonne de flux

46
Stanko

Je pense que vous pouvez utiliser loc si vous devez mettre à jour deux colonnes avec la même valeur:

_df1.loc[df1['stream'] == 2, ['feat','another_feat']] = 'aaaa'
print df1
   stream        feat another_feat
a       1  some_value   some_value
b       2        aaaa         aaaa
c       2        aaaa         aaaa
d       3  some_value   some_value
_

Si vous avez besoin d'une mise à jour séparée, une option est d'utiliser:

_df1.loc[df1['stream'] == 2, 'feat'] = 10
print df1
   stream        feat another_feat
a       1  some_value   some_value
b       2          10   some_value
c       2          10   some_value
d       3  some_value   some_value
_

Une autre option courante consiste à utiliser numpy.where :

_df1['feat'] = np.where(df1['stream'] == 2, 10,20)
print df1
   stream  feat another_feat
a       1    20   some_value
b       2    10   some_value
c       2    10   some_value
d       3    20   some_value
_

EDIT: Si vous avez besoin de diviser toutes les colonnes sans stream où condition est True, utilisez:

_print df1
   stream  feat  another_feat
a       1     4             5
b       2     4             5
c       2     2             9
d       3     1             7

#filter columns all without stream
cols = [col for col in df1.columns if col != 'stream']
print cols
['feat', 'another_feat']

df1.loc[df1['stream'] == 2, cols ] = df1 / 2
print df1
   stream  feat  another_feat
a       1   4.0           5.0
b       2   2.0           2.5
c       2   1.0           4.5
d       3   1.0           7.0
_
90
jezrael

Vous pouvez faire la même chose avec .ix, comme ceci:

In [1]: df = pd.DataFrame(np.random.randn(5,4), columns=list('abcd'))

In [2]: df
Out[2]: 
          a         b         c         d
0 -0.323772  0.839542  0.173414 -1.341793
1 -1.001287  0.676910  0.465536  0.229544
2  0.963484 -0.905302 -0.435821  1.934512
3  0.266113 -0.034305 -0.110272 -0.720599
4 -0.522134 -0.913792  1.862832  0.314315

In [3]: df.ix[df.a>0, ['b','c']] = 0

In [4]: df
Out[4]: 
          a         b         c         d
0 -0.323772  0.839542  0.173414 -1.341793
1 -1.001287  0.676910  0.465536  0.229544
2  0.963484  0.000000  0.000000  1.934512
3  0.266113  0.000000  0.000000 -0.720599
4 -0.522134 -0.913792  1.862832  0.314315

EDIT

Après les informations supplémentaires, les éléments suivants renverront toutes les colonnes - dans lesquelles certaines conditions sont remplies - avec des valeurs divisées par deux:

>> condition = df.a > 0
>> df[condition][[i for i in df.columns.values if i not in ['a']]].apply(lambda x: x/2)

J'espère que ça aide!

3
Thanos