Добавить 2 кадра данных вместе, только если значение из столбца в df2 находится в df1 - PullRequest
1 голос
/ 22 марта 2020

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

Каждое вложение можно сопоставить с его родительским электронным письмом, используя GROUPID, который будет соответствовать GROUPID электронного письма (так как они находятся в одной группе документов). Примеры таблиц ниже:

Фрейм данных родительских сообщений 1

Фрейм данных вложений 2

Обязательный выходной фрейм данных 3

Обратите внимание, что из приведенных выше примеров два вложения с GROUPIDs DO C -000000011 и DO C -000000028 не включены в окончательный вывод, поскольку у них нет соответствующего родительского адреса электронной почты в родительском элементе. Электронная почта

Я успешно написал код для этого, однако он крайне неэффективен. Сначала я сравниваю каждый из GROUPID для каждой строки в фрейме данных 'attachments' с фреймом данных 'parent_emails'. Результат (true или false) передается в серию, которая затем отображается обратно в фрейм данных вложений в новый столбец «Имеет родительский адрес электронной почты». Затем я объединяю фрейм данных «parent_emails» и фрейм данных вложений (фильтр по «Has Parent Email» == True). Ниже приведен фрагмент кода:

has_email = pd.Series({})
for index, row in attachments.iterrows():
    if (len(parent_emails[parent_emails['GROUPID'] 
                             == row['GROUPID']]) >0):
        has_email[index]=True
    else:
        has_email[index]=False

attachments.loc[:,'Has Parent Email'] = has_email

emails_attachments = parent_emails.append(
    attachments[attachments['Has Parent Email']==True])

Это дает мне требуемый результат, но должен быть более эффективный способ, и я буду благодарен за любые предложения.

Заранее спасибо.

Ответы [ 2 ]

0 голосов
/ 22 марта 2020

Рассмотрите возможность получения уникального списка идентификаторов между обоими фреймами данных с помощью merge, затем отфильтруйте по спискам с помощью isin или query и объедините два подмножества:

shared_ids = pd.merge(emails, attachments, on='GROUPID')['GROUPID'].unique().tolist()

# CONCATENATE WITH LIST FILTERING (TWO EQUAL VERSIONS)
email_attachments = (pd.concat([emails[emails['GROUPID'].isin(shared_ids)],
                                attachments.query("GROUPID == @shared_ids")],
                               sort = False)
                      .reset_index(drop = True)
                    )

Для демонстрации с данные:

emails = pd.DataFrame({'Parent': [True, True],
                       'DOCID': ['DOC008', 'DOC023'],
                       'GROUPID': ['DOC008', 'DOC023'],
                       'FileName': ['epe model for 01/25/02', 'PLEASE READ'],
                       'FileType': ['Microsoft Outlook Note', 'Microsoft Outlook Note']})

attachments = pd. DataFrame({'EmailAttachment': ['Attachment']*4,
                             'DOCID': ['DOC008', 'DOC012', 'DOC024', 'DOC029'],
                             'GROUPID': ['DOC008', 'DOC011', 'DOC023', 'DOC028'],
                             'FileName': ['1-25act.xls', '1-29act.xls', 
                                          'Certification.doc', 'Certification.doc'],
                             'FileType': ['Microsoft Excel Spreadsheet', 'Microsoft Excel Spreadsheet',
                                          'Microsoft Word Document', 'Microsoft Word Document']})

shared_ids = pd.merge(emails, attachments, on='GROUPID')['GROUPID'].unique().tolist()

email_attachments = (pd.concat([emails[emails['GROUPID'].isin(shared_ids)],
                                attachments.query("GROUPID == @shared_ids")],
                               sort = False)
                      .reset_index(drop = True)
                    )

email_attachments
#   Parent   DOCID GROUPID                FileName                     FileType EmailAttachment
# 0   True  DOC008  DOC008  epe model for 01/25/02       Microsoft Outlook Note             NaN
# 1   True  DOC023  DOC023             PLEASE READ       Microsoft Outlook Note             NaN
# 2    NaN  DOC008  DOC008             1-25act.xls  Microsoft Excel Spreadsheet      Attachment
# 3    NaN  DOC024  DOC023       Certification.doc      Microsoft Word Document      Attachment
0 голосов
/ 22 марта 2020

Я предлагаю ознакомиться с руководством пользователя Pandas, чтобы узнать больше о том, как объединять, объединять и объединять кадры данных: https://pandas.pydata.org/pandas-docs/stable/user_guide/merging.html

Как правило, вам не следует приходится перебирать строки ваших фреймов данных, чтобы объединить их вместе!

Сложно помочь вам, не зная, как организованы кадры данных, которые вы пытаетесь добавить, но если «GROUPID» является единственным столбцом, который совместно использует «parent_emails» и «attachments», то вы могли бы go с concat:

required_output = pd.concat([parent_emails, attachments], axis=1, join='inner')

Установка соединения с внутренним компонентом предотвратит появление строк, содержащих GROUPID, которые не имеют эквивалента в "parent_email" ( например DO C -000000011) от появления в объединенном фрейме данных.

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