Панды: сопоставление значений из двух фреймов данных - многие к одному

У меня есть два кадра данных, которые мне нужно сопоставить по строке. Когда происходит совпадение, мне нужно увеличить значение +1 в поле в df1. df2 имеет несколько совпадений с df1. Я не хочу объединять кадры данных, просто обновляю df1 на основе совпадения с df2.

Основная логика в моей голове: прочитать первую строку df1, а затем попытаться сопоставить TRANID с каждой строкой df2. При совпадении добавьте +1 к значению NUMINSTS. Затем вернитесь назад и сделайте то же самое для следующей строки на df1. Я просто не уверен, как подойти к этому в Python/Pandas.

Я старый программист COBOL и только изучаю Python/Pandas, поэтому любая помощь очень ценится.

    Input Data
    
    df1:
    
    TRANID      NUMINSTS
    60000022    22
    60000333    6
    70000001    15
    70000233    60
    
    df2:

    TRANID
    60000333
    70000233
    70000233

    Output

    df3:

    TRANID      NUMINSTS
    60000022    22
    60000333    7   #incremented by 1
    70000001    15
    70000233    62  #incremented by 2

Большое спасибо за все ответы. Это именно то, что мне нужно. В Python/Pandas так много способов манипулировать данными, что я действительно не знал, с чего начать.

Alakarr 22.04.2022 20:46
Анализ настроения постов в Twitter с помощью Python, Tweepy и Flair
Анализ настроения постов в Twitter с помощью Python, Tweepy и Flair
Анализ настроения текстовых сообщений может быть настолько сложным или простым, насколько вы его сделаете. Как и в любом ML-проекте, вы можете выбрать...
7 лайфхаков для начинающих Python-программистов
7 лайфхаков для начинающих Python-программистов
В этой статье мы расскажем о хитростях и советах по Python, которые должны быть известны разработчику Python.
Установка Apache Cassandra на Mac OS
Установка Apache Cassandra на Mac OS
Это краткое руководство по установке Apache Cassandra.
Сертификатная программа "Кванты Python": Бэктестер ансамблевых методов на основе ООП
Сертификатная программа "Кванты Python": Бэктестер ансамблевых методов на основе ООП
В одном из недавних постов я рассказал о том, как я использую навыки количественных исследований, которые я совершенствую в рамках программы TPQ...
Создание персонального файлового хранилища
Создание персонального файлового хранилища
Вы когда-нибудь хотели поделиться с кем-то файлом, но он содержал конфиденциальную информацию? Многие думают, что электронная почта безопасна, но это...
Создание приборной панели для анализа данных на GCP - часть I
Создание приборной панели для анализа данных на GCP - часть I
Недавно я столкнулся с интересной бизнес-задачей - визуализацией сбоев в цепочке поставок лекарств, которую могут просматривать врачи и...
0
1
60
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

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

Мы можем фильтровать на основе значений в df2 и продолжать добавлять или изменять значения в df1.

import pandas as pd

df1 = pd.DataFrame({"TRAINID":["60000022", "60000333", "70000001", "70000233"], "NUMINSTS":[22,6,15,60]})
df2 = pd.DataFrame({"TRAINID":[ "60000333", "70000233", "70000233"]})

def add_num(df1,df2):
    for id in list(df2["TRAINID"]):
        df1.loc[df1["TRAINID"] == id, "NUMINSTS"] += 1
    return df1

df3 = add_num(df1,df2)
print(df3)

Не удовлетворяет случай, если бы в df2 был новый транид.

Michał Mazur 22.04.2022 20:44

ОП не указал такое требование

Upasana Mittal 22.04.2022 22:13

Вы можете попробовать:

    df1 = pd.DataFrame({'TRANID':[60000022, 60000333, 70000001, 70000233],
'NUMINSTS':[22,6,15,60]})

дф1:

    TRANID  NUMINSTS
0   60000022          22
1   60000333           6
2   70000001          15
3   70000233          60

df2 = pd.DataFrame({'TRANID':[60000333, 70000233, 70000233]})

дф2:

    TRANID
0   60000333
1   70000233
2   70000233

Создайте словарь количества значений TRANID из df2:

d = df2['TRANID'].value_counts().to_dict()

Скопируйте df3 из df1 и обновите столбец NUMINSTS, например, если TRANID находится в приведенном выше словаре, увеличьте значение счетчика, в противном случае оставьте его прежним:

df3 = df1.copy()


df3['NUMINSTS'] = df3.apply(
        lambda row: 
    row['NUMINSTS']+d[row['TRANID']] if row['TRANID'] in d else row['NUMINSTS'], axis=1)

Если вам не нужны строки, которые не совпадают, вы можете заменить None, как показано ниже, а затем удалить строки со значениями None:

df3['NUMINSTS'] = df3.apply(
            lambda row: 
        row['NUMINSTS']+d[row['TRANID']] if row['TRANID'] in d else None, axis=1)
df3.dropna(subset=['NUMINSTS'], inplace=True)
df3['NUMINSTS'] = df3['NUMINSTS'].astype(int)
df3.reset_index(inplace=True,drop=True)

Выход df3:

    TRANID    NUMINSTS
0   60000333         7
1   70000233        62

Не удовлетворяет случай, если в df2 был новый транид

Michał Mazur 22.04.2022 20:44

@MichałMazur, что делать, если у вас есть новый TRANID в df2? он не влияет на NUMINSTS df1, если он не найден в df1.

SomeDude 22.04.2022 20:48

Да, но я предполагаю, что он хотел бы добавить этот новый номер trainid в df1 с numinst=1, но это может быть только мое предположение.

Michał Mazur 22.04.2022 20:55

Просто обойдет транид в df2, если совпадений не будет найдено. Не хотелось бы добавлять его в df1.

Alakarr 22.04.2022 21:40

Мне нравится использование лямбда, и я применяю здесь. Это должно быть быстрее

Upasana Mittal 22.04.2022 22:12

@Alakarr Я добавил код для удаления строк, если совпадений нет.

SomeDude 22.04.2022 22:17

Вам нужны два случая:

  1. Tranid существует в df1
  2. Tranid не существует в df1.

Вот ваш код:

import pandas as pd
df1=pd.DataFrame({'tranid':[1,2,3],'numinst':[2,4,6]})
df2=pd.DataFrame({'tranid':[1,2,4]})
tranvalues=df1['tranid']
for i in range(len(df2)):
    if df2['tranid'][i] in tranvalues:
        df1['numinst'][df1['tranid']==df2['tranid'][i]]=df1['numinst']+1
    else:
        df1.loc[len(df1.index)]=[df2['tranid'][i],1]

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