根据各种条件组合行以具有相同的 ID

Posted

技术标签:

【中文标题】根据各种条件组合行以具有相同的 ID【英文标题】:Combine Rows to Have Same ID Based on Various Criteria 【发布时间】:2021-10-08 05:53:25 【问题描述】:

我有超过 900,000 条联系人记录,需要找到一种方法来合并具有相同“名字”和“姓氏”以及任何一个相同的“街道地址”的记录', '邮件或者电话'。我想保留最近的“上次修改日期”作为主要记录的记录,并且所有重复项都将其“联系人 ID”更新为主要记录之一。 我还想保留原始联系人 ID 以在新列中跟踪! 当然,我希望在合并时忽略 Null。 我的代码很长,所以这里有一个下载链接(我不想在这里占用太多空间):https://drive.google.com/file/d/1tJRr4IyHwHf2NF80j1LO7bTDakXRUtVM/view?usp=sharing

【问题讨论】:

如果可以的话,提供预期的minimal, reproducible example 会很有帮助,这有助于更快地进行测试并以更直接的方式突出您当前的误解,而不是对您遇到的问题含糊其辞. 你可以使用groupby 和几个聚合函数,比如这里,也许是:https://***.com/questions/36271413/pandas-merge-nearly-duplicate-rows-based-on-column-value 【参考方案1】:

想法是按修改日期对数据框进行排序,然后遍历行,将组合保存为字典中的字符串作为键。

dataframe.sort(by = ['Last Modified Date'], ascending = False)
dataframe['old contact id'] = ""
dict1 = 
for i in range(len(dataframe)):
    if dict1.get(str(dataframe['First Name'][i] + dataframe['Last Name'][i] + dataframe['email'][i])):
        df.loc[df['contact id'] == dict1[str(dataframe['First Name'][i] + dataframe['Last Name'][i] + dataframe['email'][i])]]['old contact id'] = df['contact id'][i]
    elif dict1.get(str(dataframe['First Name'][i] + dataframe['Last Name'][i] + dataframe['address'][i])):
        df.loc[df['contact id'] == dict1[str(dataframe['First Name'][i] + dataframe['Last Name'][i] + dataframe['address'][i])]]['old contact id'] = df['contact id'][i]
    elif dict1.get(str(dataframe['First Name'][i] + dataframe['Last Name'][i] + dataframe['phone'][i])):
        df.loc[df['contact id'] == dict1[str(dataframe['First Name'][i] + dataframe['Last Name'][i] + dataframe['phone'][i])]]['old contact id'] = df['contact id'][i]
    else:
        dict1[str(dataframe['First Name'][i] + dataframe['Last Name'][i] + dataframe['email'][i])] = = str(dataframe['Contact id'][i]
        dict1[str(dataframe['First Name'][i] + dataframe['Last Name'][i] + dataframe['address'][i])] = = str(dataframe['Contact id'][i]
        dict1[str(dataframe['First Name'][i] + dataframe['Last Name'][i] + dataframe['phone'][i])] = str(dataframe['Contact id'][i]

最后如果旧的修改为空,则删除该列。

dataframe = dataframe.loc[dataframe['old contact id'] != ""]

代码很长,但排序后会给出O(n) 的复杂性。

【讨论】:

我遇到了很多语法错误。另外,你在哪里定义 df?【参考方案2】:

拒绝了我发布的第一个答案,然后更新了更多要求的问题,请注意:本网站不是免费的代码编写服务。而且您的代码链接不起作用(至少目前如此)。

鉴于:

import pandas as pd
import numpy as np

df = pd.DataFrame('First_Name': 0: 'Greg',  1: 'Greg',  2: 'John',  3: 'John',  4: 'Ryan',  5: 'Ryan', \
                    'Last_Name': 0: 'Li', 1: 'Li', 2: 'Doe', 3: 'Doe', 4: 'Lin', 5: 'Lin', \
                    'ContactID': 0: 123, 1: 1877, 2: 566, 3: 234, 4: 789, 5: 52, \
                    'Last_Modified_Date': 0: '2021-04-08',  1: '2019-05-06',  2: '2018-02-03', \
                                           3: '2014-05-07',  4: '2019-06-07',  5: '2018-06-07', \
                    'Email': 0: 'grey.li@gmail.com',  1: 'grey.li@gmail.com',  2: 'Johndeo@yahoo.com',  \
                              3: 'Johndeo@aol.net',  4: 'lin@hotmail.com',  5: np.nan, \
                    'Address': 0: '44 Sherman',  1: np.nan,  2: '87 Branch Ave',  3: '87 Branch Ave', \
                                4: '84 Newport',  5: np.nan, 'Phone': 0: '999-999-9999',  1: np.nan, \
                                                                     2: '890-523-4667',  3: np.nan,  4: \
                                                                     '678-900-000',  5: '678-900-000')

print(df)

试试:

df['Last_Modified_Date'] = pd.to_datetime(df['Last_Modified_Date'], format='%Y-%m-%d')
df = df.sort_values(by='Last_Modified_Date')
df['AllContactID'] = df['ContactID'].map(str)
df = df.replace(np.nan, '', regex=False)
df = df.groupby(by=['First_Name', 'Last_Name'], as_index=False)\
    .agg('Last_Modified_Date': 'last', 'ContactID' : 'last', \
          'Email' : ', '.join, 'Address' : ', '.join, 'Phone' : ', '.join, 'AllContactID' : ', '.join)  
df = df.replace(r'(.*?)(,\s)\1', r', \1', regex=True)
df = df.replace(r'^, (.*)$', r'\1', regex=True)
df = df.replace(r', $', r'', regex=True)
#df['AllContactID'] = df.AllContactID.apply(lambda x: list(x.split(', ')))
#df['AllContactID'] = df.AllContactID.apply(lambda x: list(map(int, x)))

print(df)

【讨论】:

以上是关于根据各种条件组合行以具有相同的 ID的主要内容,如果未能解决你的问题,请参考以下文章

有条件地格式化子表单中的组合框

根据条件按 ID 组合重叠日期

使用 XSLT 组合具有相同 ID 及其值的节点 (XML)

将 12 个具有不同“where”条件的 MS Access 查询组合到一个查询中

XSLT 将具有相同 ID 的行项目组合到单独的记录中

Javascript合并并组合具有相同ID的对象