Изменить столбцы определенного фрейма данных, используя другой фрейм данных

У меня есть определенный фрейм данных (df1) с некоторыми значениями переменной с именем «MP10».

df = data = {
  "day": [1, 2, 3, 4, 5, 6, 7],
  "month": [1, 1, 4, 4, 7, 7, 7],
  "year": [2015, 2015, 2016, 2017, 2017, 2019, 2019,],
  "mp10": [10, 15, 20, 5, 7, 14, 18]  
}

df1 = pd.DataFrame(df)
df1

Но мне нужно изменить значения NaN для определенных дней. И я создал еще один фрейм данных (df2), чтобы найти эти конкретные дни.

df = data = {
  "day": [2, 5, 7],
  "month": [1, 7, 7],
  "year": [2015, 2017, 2019,],
  "mp10": [np.NaN, np.NaN, np.NaN]  
}

df2 = pd.DataFrame(df)
df2

Я думал, что с помощью pd.merge можно изменить значения, но не получилось.

Как я могу выбрать NaN из df2 и изменить их в df1?

Изображения данных не принимаются, необходимо предоставить минимально воспроизводимый пример и четкое описание логики.

mozway 01.07.2024 20:02

Я подумал, что размещение изображений из моего фрейма данных может помочь. Но я изменю это

Daniel M M 01.07.2024 20:06

@DanielMM дело не в том, что наличие данных бесполезно (бесполезно?), нам просто сложно работать с данными, представленными в виде изображений. Возможность копирования/вставки очень помогает. что ты уже испробовал? Также сложно отлаживать код, которого у нас нет.

JRiggles 01.07.2024 20:11

Кроме того, данные с ... неоднозначны, лучше создать небольшой, но содержательный пример и предоставить соответствующий ожидаемый результат.

mozway 01.07.2024 20:14

Я создал пример. Возможно, это работает лучше, чем эти изображения.

Daniel M M 01.07.2024 20:17

каков ваш ожидаемый результат?

iBeMeltin 01.07.2024 20:29

Я ожидал, что столбец «MP10» будет выглядеть следующим образом: [10, NaN, 20, 5, NaN, 14, NaN]

Daniel M M 01.07.2024 20:41

Спасибо, теперь это гораздо яснее.

mozway 01.07.2024 20:48
Почему в 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 может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
8
75
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вы можете использовать слияние с indicator=True, чтобы определить индексы, которые нужно удалить:

idx = (df1.reset_index()
       .merge(df2, on=['day', 'month', 'year'],
              how='left', indicator=True)
       .query('_merge == "both"')['index']
      )

df1.loc[idx, 'mp10'] = None

Вариант с использованием логического индексирования:

mask = (df1.merge(df2, on=['day', 'month', 'year'],
                  how='left', indicator=True)
        ['_merge'].eq('both')
        .tolist() # merge doesn't maintain the index
       )

df1.loc[mask, 'mp10'] = None

Выход:

   day  month  year  mp10
0    1      1  2015  10.0
1    2      1  2015   NaN
2    3      4  2016  20.0
3    4      4  2017   5.0
4    5      7  2017   NaN
5    6      7  2019  14.0
6    7      7  2019   NaN

Или, если вам нужен новый DataFrame:

out = (df1.merge(df2.assign(mp10=1), on=['day', 'month', 'year'],
                 how='left', suffixes=(None, '_mask'))
          .assign(mp10=lambda x: x['mp10'].mask(x.pop('mp10_mask').eq(1)))
      )

Большой! Это сработало! Я не знал о «.query», но я прочитаю и узнаю о нем больше.

Daniel M M 01.07.2024 20:55

Я снова просмотрел этот код и заметил, что он работает не идеально. По какой-то причине, когда у df1 было число, оно не изменилось для NaN.

Daniel M M 02.07.2024 15:25

@Дэниел, можешь быть более откровенным?

mozway 02.07.2024 15:27

Я создал еще один ответ и объяснил там. Спасибо за вашу помощь

Daniel M M 02.07.2024 15:37

@DanielMM не используйте ответ, отредактируйте свой вопрос и добавьте следующий пример после существующего. Кроме того, не используйте изображения данных, а предоставьте два входных параметра (df1/df2) в качестве конструкторов DataFrame, как это сделано сейчас для первого примера.

mozway 02.07.2024 15:48

Хорошо, я поменяю. Спасибо!

Daniel M M 02.07.2024 15:49

Я посмотрел на код и понял, что ошибся и допустил ошибку. Прошу прещения за это.

Daniel M M 02.07.2024 15:59

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

import pandas as pd
import numpy as np

df = pd.DataFrame(
    {
        "day": [1, 2, 3, 4, 5, 6, 7],
        "month": [1, 1, 4, 4, 7, 7, 7],
        "year": [2015, 2015, 2016, 2017, 2017, 2019, 2019],
        "mp10": [10, 15, 20, 5, 7, 14, 18],
    }
)

df = df.assign(datetime=pd.to_datetime(df[["day", "month", "year"]]))
df = df.set_index("datetime")

to_change = pd.to_datetime(
    {"day": [2, 5, 7], "month": [1, 7, 7], "year": [2015, 2017, 2019]}
)

df.loc[to_change, "mp10"] = np.nan
>>> df
            day  month  year  mp10
datetime
2015-01-01    1      1  2015  10.0
2015-01-02    2      1  2015   NaN
2016-04-03    3      4  2016  20.0
2017-04-04    4      4  2017   5.0
2017-07-05    5      7  2017   NaN
2019-07-06    6      7  2019  14.0
2019-07-07    7      7  2019   NaN

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