Comment mettre à jour des valeurs dans une ligne spécifique dans une DataFrame Python Pandas?

avec les méthodes d'indexation nice dans Pandas, Je n'ai aucun problème à extraire des données de différentes façons. D'un autre côté, je suis encore confus sur la façon de changer des données dans une base de données existante.

dans le code suivant j'ai deux DataFrames et mon but est de mettre à jour des valeurs dans une ligne spécifique dans le premier df à partir des valeurs du second DF. Comment puis-je y parvenir?

import pandas as pd
df = pd.DataFrame({'filename' :  ['test0.dat', 'test2.dat'], 
                                  'm': [12, 13], 'n' : [None, None]})
df2 = pd.DataFrame({'filename' :  'test2.dat', 'n':16}, index=[0])

# this overwrites the first row but we want to update the second
# df.update(df2)

# this does not update anything
df.loc[df.filename == 'test2.dat'].update(df2)

print(df)

donne

   filename   m     n
0  test0.dat  12  None
1  test2.dat  13  None

[2 rows x 3 columns]

mais comment puis-je obtenir ceci:

    filename   m     n
0  test0.dat  12  None
1  test2.dat  13  16

[2 rows x 3 columns]
21
demandé sur Alexander 2014-06-04 16:02:26

3 réponses

Alors tout d'abord, pandas mises à jour à l'aide de l'index. Quand une commande update ne met pas à jour quoi que ce soit, cochez à la fois le côté gauche et le côté droit. Si pour une raison quelconque vous êtes trop paresseux pour mettre à jour les indices pour suivre votre logique d'identification, vous pouvez faire quelque chose du genre

>>> df.loc[df.filename == 'test2.dat', 'n'] = df2[df2.filename == 'test2.dat'].loc[0]['n']
>>> df
Out[331]: 
    filename   m     n
0  test0.dat  12  None
1  test2.dat  13    16

si vous voulez faire cela pour l'ensemble de la table, je suggère une méthode que je crois supérieure aux précédentes: puisque votre identifiant est filename, ensemble filename comme votre index, puis utilisez update() comme vous le souhaitiez. Les deux merge et apply() l'approche comporte des frais généraux inutiles:

>>> df.set_index('filename', inplace=True)
>>> df2.set_index('filename', inplace=True)
>>> df.update(df2)
>>> df
Out[292]: 
            m     n
filename           
test0.dat  12  None
test2.dat  13    16
29
répondu FooBar 2014-06-04 16:56:55

si vous avez une grande dataframe et seulement quelques valeurs de mise à jour, j'utiliserais apply comme ceci:

import pandas as pd

df = pd.DataFrame({'filename' :  ['test0.dat', 'test2.dat'], 
                                  'm': [12, 13], 'n' : [None, None]})

data = {'filename' :  'test2.dat', 'n':16}

def update_vals(row, data=data):
    if row.filename == data['filename']:
        row.n = data['n']
    return row

df.apply(update_vals, axis=1)
3
répondu zach 2014-06-04 14:05:42

il y a probablement quelques façons de faire ceci, mais une approche serait de fusionner les deux dataframes ensemble sur la colonne filename/m, puis peupler la colonne 'n' À partir de la bonne dataframe si une correspondance était trouvée. Les n_x, n_y dans le code se réfèrent aux images de gauche/droite dans la fusion.

In[100] : df = pd.merge(df1, df2, how='left', on=['filename','m'])

In[101] : df
Out[101]: 
    filename   m   n_x  n_y
0  test0.dat  12  None  NaN
1  test2.dat  13  None   16

In[102] : df['n'] = df['n_y'].fillna(df['n_x'])

In[103] : df = df.drop(['n_x','n_y'], axis=1)

In[104] : df
Out[104]: 
    filename   m     n
0  test0.dat  12  None
1  test2.dat  13    16
2
répondu chrisb 2014-06-04 12:15:32