web-dev-qa-db-fra.com

itérer sur un fichier de données de pandas et mettre à jour la valeur

J'essaie de parcourir un cadre de données de pandas et de mettre à jour la valeur si la condition est remplie, mais j'obtiens une erreur.

for line, row in enumerate(df.itertuples(), 1):
    if row.Qty:
        if row.Qty == 1 and row.Price == 10:
            row.Buy = 1
AttributeError: can't set attribute
7
Sun

Une première itération dans les pandas est possible, mais très lente, une autre solution vectorisée est utilisée.

Je pense que vous pouvez utiliser iterrows si vous avez besoin d'itérer:

for idx, row in df.iterrows():
    if  df.loc[idx,'Qty'] == 1 and df.loc[idx,'Price'] == 10:
        df.loc[idx,'Buy'] = 1

Mais il vaut mieux utiliser des solutions vectorisées - définissez la valeur avec un masque booléen avec loc:

mask = (df['Qty'] == 1) & (df['Price'] == 10)
df.loc[mask, 'Buy'] = 1

Ou solution avec mask :

df['Buy'] = df['Buy'].mask(mask, 1)

Ou si vous avez besoin de if...else, utilisez numpy.where :

df['Buy'] = np.where(mask, 1, 0)

Échantillons.

Définir les valeurs par conditions:

df = pd.DataFrame({'Buy': [100, 200, 50], 
                   'Qty': [5, 1, 1], 
                   'Name': ['Apple', 'pear', 'banana'], 
                   'Price': [1, 10, 10]})

print (df)
   Buy    Name  Price  Qty
0  100   Apple      1    5
1  200    pear     10    1
2   50  banana     10    1

mask = (df['Qty'] == 1) & (df['Price'] == 10)


df['Buy'] = df['Buy'].mask(mask, 1)
print (df)
   Buy    Name  Price  Qty
0  100   Apple      1    5
1    1    pear     10    1
2    1  banana     10    1
df['Buy'] = np.where(mask, 1, 0)
print (df)
   Buy    Name  Price  Qty
0    0   Apple      1    5
1    1    pear     10    1
2    1  banana     10    1
17
jezrael

Ok, si vous souhaitez définir des valeurs dans df, vous devez suivre les valeurs index.

Option 1
en utilisant itertuples

# keep in mind `row` is a named Tuple and cannot be edited
for line, row in enumerate(df.itertuples(), 1):  # you don't need enumerate here, but doesn't hurt.
    if row.Qty:
        if row.Qty == 1 and row.Price == 10:
            df.set_value(row.Index, 'Buy', 1)

Option 2
en utilisant iterrows 

# keep in mind that `row` is a `pd.Series` and can be edited...
# ... but it is just a copy and won't reflect in `df`
for idx, row in df.iterrows():
    if row.Qty:
        if row.Qty == 1 and row.Price == 10:
            df.set_value(idx, 'Buy', 1)

option 3
en utilisant la boucle droite avec get_value

for idx in df.index:
    q = df.get_value(idx, 'Qty')
    if q:
        p = df.get_value(idx, 'Price')
        if q == 1 and p == 10:
            df.set_value(idx, 'Buy', 1)
9
piRSquared

la méthode pandas.DataFrame.set_value est obsolète à partir de 0.21.0 pd.DataFrame.set_value

Utilisez pandas.Dataframe.at

for index, row in df.iterrows():
        if row.Qty and row.Qty == 1 and row.Price == 10:
            df.at[index,'Buy'] = 1
0
Saurabh