簡體   English   中英

Python - 根據部分字符串匹配將行保留在數據框中

[英]Python - keep rows in dataframe based on partial string match

我有 2 個數據框:
df1 是郵箱和電子郵件 ID 的列表
df2 顯示已批准域的列表

我從 Excel 表中讀取了兩個數據框

    xls = pd.ExcelFile(input_file_shared_mailbox)
    df = pd.read_excel(xls, sheet_name = sheet_name_shared_mailbox)

我只想在 df1 中保留記錄,其中 df1[Email_Id] 包含 df2[approved_domain]

    print(df1)  
        Mailbox Email_Id  
    0   mailbox1   abc@gmail.com  
    1   mailbox2   def@yahoo.com  
    2   mailbox3   ghi@msn.com  

    print(df2)  
        approved_domain  
    0   msn.com  
    1   gmail.com  

我想要 df3 基本上顯示

    print (df3)  
        Mailbox Email_Id  
    0   mailbox1   abc@gmail.com  
    1   mailbox3   ghi@msn.com  

這是我現在擁有的代碼,我認為它很接近,但我無法弄清楚語法中的確切問題

df3 = df1[df1['Email_Id'].apply(lambda x: [item for item in x if item in df2['Approved_Domains'].tolist()])]

但是得到這個錯誤

TypeError: unhashable type: 'list'

我花了很多時間在論壇上尋找解決方案,但找不到我要找的東西。 感謝所有的幫助。

所以這些是你需要遵循的步驟來為你的兩個數據框做你想做的事情

1.將您的 email_address 列拆分為兩個單獨的列

     df1['add'], df1['domain'] = df1['email_address'].str.split('@', 1).str

2.然后刪除添加列以保持數據框干凈

      df1 = df1.drop('add',axis =1)

3.通過不在“域”列中選擇與“approved_doman”列不匹配的任何值,獲取僅包含您想要的值的新數據框

      df_new = df1[~df1['domain'].isin(df2['approved_domain'])]

4. 刪除 df_new 中的 'domain' 列

      df_new = df_new.drop('domain',axis = 1)

這就是結果

    mailbox     email_address
1   mailbox2    def@yahoo.com
2   mailbox3    ghi@msn.com

您可以使用動態創建的正則表達式來搜索列表中的有效域並最終將其過濾掉。

這是我們參考的代碼。

 # -*- coding: utf-8 -*-

import pandas as pd
import re

mailbox_list = [
        ['mailbox1', 'abc@gmail.com'],
        ['mailbox2', 'def@yahoo.com'],
        ['mailbox3', 'ghi@msn.com']]

valid_domains = ['msn.com', 'gmail.com']

df1 = pd.DataFrame(mailbox_list, columns=['Mailbox', 'EmailID'])
df2 = pd.DataFrame(valid_domains)

valid_list = []

for index, row in df1.iterrows():
    for idx, record in df2.iterrows():
        if re.search(rf"@{record[0]}", row[1], re.IGNORECASE):
            valid_list.append([row[0], row[1]])

df3 = pd.DataFrame(valid_list, columns=['Mailbox', 'EmailID'])
print(df3)

這個的輸出是:

    Mailbox        EmailID
0  mailbox1  abc@gmail.com
1  mailbox3    ghi@msn.com

解決方案

df1 = {'MailBox': ['mailbox1', 'mailbox2', 'mailbox3'], 'Email_Id': ['abc@gmail.com', 'def@yahoo.com', 'ghi@msn.com']}
df2 = {'approved_domain':['msn.com', 'gmail.com']}

mailboxes, emails = zip( # unzip the columns
    *filter( # filter 
        lambda i: any([  # i = ('mailbox1', 'abc@gmail.com')
            approved_domain in i[1] for approved_domain in df2['approved_domain']
        ]),
        zip(df1['MailBox'], df1['Email_Id']) # zip the columns
    )
)

df3 = {
    'MailBox': mailboxes, 
    'Email_I': emails
}
print(df3)

輸出:

> {'Email_ID': ('abc@gmail.com', 'ghi@msn.com'), 'MailBox': ('mailbox1', 'mailbox3')}                                                                                                                                                             

一些注意事項:

這段代碼的很大一部分基本上只是用於解析數據結構。 壓縮和解壓縮僅用於將列列表轉換為行列表並返回。 如果你已經有一個行列表,你只需要做過濾部分

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM