根据各种条件组合行以具有相同的 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的主要内容,如果未能解决你的问题,请参考以下文章
使用 XSLT 组合具有相同 ID 及其值的节点 (XML)