Как обновить значения в определенной строке в Python Pandas DataFrame?

С хорошими методами индексирования в Pandas у меня нет проблем с извлечением данных по-разному. С другой стороны, я все еще смущен тем, как изменять данные в существующем DataFrame.

В следующем коде у меня есть два DataFrames, и моя цель - обновить значения в определенной строке в первом df из значений второго df. Как я могу достичь этого?

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)

дает

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

[2 rows x 3 columns]

но как я могу достичь этого:

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

[2 rows x 3 columns]

Ответы

Ответ 1

Итак, прежде всего, pandas обновляется с использованием индекса. Когда команда обновления ничего не обновляет, проверьте как правую, так и левую сторону. Если по какой-то причине вы слишком ленивы, чтобы обновлять индексы, чтобы следовать логике идентификации, вы можете сделать что-то в соответствии с

>>> 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

Если вы хотите сделать это для всей таблицы, я предлагаю метод, который, как мне кажется, превосходит предыдущие: поскольку ваш идентификатор filename, установите filename в качестве вашего индекса, а затем используйте update() как вы хотели. Оба подхода merge и apply() содержат ненужные служебные данные:

>>> 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

Ответ 2

Если у вас есть один большой фреймворк данных и только несколько значений обновления, которые я бы использовал, примените следующее:

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

Есть, вероятно, несколько способов сделать это, но один из подходов состоял бы в том, чтобы объединить два файла данных вместе в столбце filename/m, а затем заполнить столбец "n" из правильного фрейма данных, если совпадение было найдено. N_x, n_y в коде относятся к левым/правым фреймам данных в слиянии.

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