Python Pandas: обновлять значения фрейма данных из другого фрейма данных

1

У меня есть два этих фрейма: (обновление: я добавил один stuff столбца в df1 чтобы указать, что два блока данных не имеют одинаковых схем)

df1 = pd.DataFrame({'id': ['1','2','3'], 
                    'val': [0, 0, 0], 
                    'stuff': ['foo', 'bar', 'spam']})
df2 = pd.DataFrame({'id': ['2','3'], 'val': [10, 20]})

print(df1)
  id  val stuff
0  1    0   foo
1  2    0   bar
2  3    0  spam

print(df2)
  id  val
0  2   10
1  3   20

Я хочу обновить значения в df1 val со значениями из df2 val на основе столбца id. Желаемый результат после преобразования на df1:

print(df1)
  id  val stuff
0  1    0   foo
1  2   10   bar
2  3   20  spam

Я мог бы использовать объединение (merge), но затем мне понадобилось бы еще несколько шагов, чтобы закончить ожидаемый результат (листинг столбца от float до int, drop column и т.д.). (Кстати, если у вас простой и элегантный способ присоединиться к нему, мне также интересно).
Я пытаюсь использовать методы нарезки, но не мог понять, как это сделать. Пример:

>>> df1.loc[df1['id'].isin(df2['id']), 'val'] = df2['val']

дает:

print(df1)
  id   val stuff
0  1   0.0   foo
1  2  20.0   bar
2  3   NaN  spam

Обновление: еще одно ограничение: не изменяйте исходный индекс df1.

Теги:
pandas
dataframe

3 ответа

1

Вы также можете сделать map

In [88]: df1['id'].map(df2.set_index('id')['val']).fillna(df1['val'])
Out[88]:
0     0.0
1    10.0
2    20.0
Name: id, dtype: float64

In [89]: df1['val'] = df1['id'].map(df2.set_index('id')['val']).fillna(df1['val'])

In [90]: df1
Out[90]:
  id   val
0  1   0.0
1  2  10.0
2  3  20.0
1

Вы можете использовать concat и drop duplicates

df = pd.concat([df1,df2]).set_index('id').drop_duplicates().reset_index()

    id  val
0   1   0
1   2   10
2   3   20

Если вы не хотите изменять оригинальный индекс, то что-то вроде этого будет работать.

df1 = pd.DataFrame({'id': ['1','2','3'], 'val': [0, 0, 0] ,
                       'stuff': ['foo', 'bar', 'spam']})
df2 = pd.DataFrame({'id': ['2','3'], 'val': [10, 20] })

df1.set_index('id', inplace=True)
df1.update(df2.set_index('id'))
df1.reset_index(inplace=True)
# df1.val = df1.val.astype(int) # convert to int

print(df1)
   id   val    stuff
0   1   0       foo
1   2   10      bar
2   3   20      spam
  • 1
    Это работает, если df1 и df2 имеют одинаковую схему. Что если в df1 есть больше столбцов? И я бы предпочел не трогать оригинальный индекс df1 . Я отредактировал вопрос, чтобы принять это во внимание.
  • 1
    @ivankeller Я обновил его снова. Надеюсь, это поможет.
0

Я нашел решение с помощью merge:

df1 = df1.merge(df2, how='left', on='id')
df1['val'] = np.where(df1['val_y'].isnull(), df1['val_x'], df1['val_y'])
# recast to int
df1['val'] = df1['val'].astype(int)
# remove extra columns
df1.drop(['val_x', 'val_y'], axis=1, inplace=True)

print(df1)
  id stuff  val
0  1   foo    0
1  2   bar   10
2  3  spam   20

Ещё вопросы

Сообщество Overcoder
Наверх
Меню