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

У меня есть два фрейма данных в Python. Я хочу обновить строки в первом фрейме данных, используя совпадающие значения из другого фрейма данных. Второй фрейм данных служит заменой.

Вот пример с такими же данными и кодом:

DataFrame 1:

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

DataFrame 2:

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

Я хочу обновить фрейм данных обновления 1 на основе совпадающего кода и имени. В этом примере Dataframe 1 следует обновить, как показано ниже:

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

Примечание. Строка с Code = 2 и Name = Company2 обновляется значением 1000 (поступающим из Dataframe 2).

import pandas as pd

data1 = {
         'Code': [1, 2, 3],
         'Name': ['Company1', 'Company2', 'Company3'],
         'Value': [200, 300, 400],

    }
df1 = pd.DataFrame(data1, columns= ['Code','Name','Value'])

data2 = {
         'Code': [2],
         'Name': ['Company2'],
         'Value': [1000],
    }

df2 = pd.DataFrame(data2, columns= ['Code','Name','Value'])

Есть указатели или подсказки?

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
36
0
45 602
10
Перейти к ответу Данный вопрос помечен как решенный

Ответы 10

Вы можете сначала объединить данные, а затем использовать numpy.where, здесь как использовать numpy.where

updated = df1.merge(df2, how='left', on=['Code', 'Name'], suffixes=('', '_new'))
updated['Value'] = np.where(pd.notnull(updated['Value_new']), updated['Value_new'], updated['Value'])
updated.drop('Value_new', axis=1, inplace=True)

   Code      Name   Value
0     1  Company1   200.0
1     2  Company2  1000.0
2     3  Company3   400.0

Спасибо. Итак, левое соединение, а затем обновление поля «Значение» с помощью «Value_new» для строк, отличных от NaN.

ProgSky 19.04.2018 21:17

Используя DataFrame.update, который выравнивается по индексам (https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.update.html):

>>> df1.set_index('Code', inplace=True)
>>> df1.update(df2.set_index('Code'))
>>> df1.reset_index()  # to recover the initial structure

   Code      Name   Value
0     1  Company1   200.0
1     2  Company2  1000.0
2     3  Company3   400.0

Это кажется наиболее идеальным решением среди всех ... но Ник, ты можешь мне помочь с одним? ... что, если бы df1 и df2 имели по 5 столбцов в каждом, но я хотел обновить только столбец «Значение», а не остальные (приведенный выше код обновляет все столбцы, относящиеся к этому "индексу") ... это возможно, пожалуйста? Пожалуйста, помогите ...

Lokkii9 01.01.2021 04:09

Вы можете использовать pd.Series.where в результате левого соединения df1 и df2

merged = df1.merge(df2, on=['Code', 'Name'], how='left')
df1.Value = merged.Value_y.where(~merged.Value_y.isnull(), df1.Value)
>>> df1
    Code    Name    Value
0   1   Company1    200.0
1   2   Company2    1000.0
2   3   Company3    400.0

Вы можете изменить строку на

df1.Value = merged.Value_y.where(~merged.Value_y.isnull(), df1.Value).astype(int)

чтобы вернуть значение как целое число.

Почему он добавляет .0 к значению? (Ничего страшного, но просто любопытно)

ProgSky 19.04.2018 21:27

@ProgSky Это потому, что тип изменился. Я обновил ответ, чтобы показать, как вернуть его на int.

Ami Tavory 19.04.2018 21:34

Предполагая, что company и code являются избыточными идентификаторами, вы также можете сделать

import pandas as pd
vdic = pd.Series(df2.Value.values, index=df2.Name).to_dict()

df1.loc[df1.Name.isin(vdic.keys()), 'Value'] = df1.loc[df1.Name.isin(vdic.keys()), 'Name'].map(vdic)

#   Code      Name  Value
#0     1  Company1    200
#1     2  Company2   1000
#2     3  Company3    400
Ответ принят как подходящий

Можно использовать concat + drop_duplicates

pd.concat([df1,df2]).drop_duplicates(['Code','Name'],keep='last').sort_values('Code')
Out[1280]: 
   Code      Name  Value
0     1  Company1    200
0     2  Company2   1000
2     3  Company3    400

Просто хочу отметить, что это решение не только обновляет фрейм записей dataframe1, но также добавляет новые записи из dataframe2, которых раньше не было в dataframe1.

mjspier 18.11.2019 09:09

Вы можете выровнять индексы, а затем использовать combine_first:

res = df2.set_index(['Code', 'Name'])\
         .combine_first(df1.set_index(['Code', 'Name']))\
         .reset_index()

print(res)

#    Code      Name   Value
# 0     1  Company1   200.0
# 1     2  Company2  1000.0
# 2     3  Company3   400.0

Это неверный ответ. Причина: объедините два объекта DataFrame, заполнив пустые значения в одном DataFrame ненулевыми значениями из другого DataFrame. Индексы строки и столбца результирующего DataFrame будут объединением двух. pandas.pydata.org/pandas-docs/stable/reference/api/… @safiqul islam упоминает ниже функцию обновления, которая, похоже, работает. pandas.pydata.org/pandas-docs/stable/reference/api/…

Corina Roca 02.03.2021 18:57
  1. Добавить набор данных
  2. Скинь дубликат на code
  3. Сортировать значения
combined_df = combined_df.append(df2).drop_duplicates(['Code'],keep='last').sort_values('Code')

Ни одно из вышеперечисленных решений не сработало для моего конкретного примера, который, я думаю, основан на dtype моих столбцов, но в конце концов я пришел к этому решению.

indexes = df1.loc[df1.Code.isin(df2.Code.values)].index
df1.at[indexes,'Value'] = df2['Value'].values

Доступна функция Обновить

пример:

df1.update(df2)

для получения дополнительной информации:

https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.update.html

Я часто что-то делаю.

Сначала я объединяю "слева":

df_merged = pd.merge(df1, df2, how = 'left', on = 'Code')

Pandas создаст столбцы с расширением '_x' (для вашего левого фрейма данных) и '_y' (для вашего правого фрейма данных)

Вам нужны те, которые пришли справа. Так что просто удалите все столбцы с _x и переименуйте _y:

for col in df_merged.columns:
    if '_x' in col:
        df_merged .drop(columns = col, inplace = True)
    if '_y' in col:
        new_name = col.strip('_y')
        df_merged .rename(columns = {col : new_name }, inplace=True)

Другие вопросы по теме