Python 迭代dataframe列中的列表元素,并与不同dataframe中的值匹配
我有两个数据帧,我希望迭代companys列中每个列表中的元素,并且仅当第一个数据帧的日期出现在第二个数据帧的日期之后时,才将其与第二个数据帧中的公司名称相匹配。我需要两列作为名称匹配项,两列作为返回的日期匹配项Python 迭代dataframe列中的列表元素,并与不同dataframe中的值匹配,python,pandas,Python,Pandas,我有两个数据帧,我希望迭代companys列中每个列表中的元素,并且仅当第一个数据帧的日期出现在第二个数据帧的日期之后时,才将其与第二个数据帧中的公司名称相匹配。我需要两列作为名称匹配项,两列作为返回的日期匹配项 df = pd.DataFrame(columns=['Customer','Companies', 'Date']) df = df.append({'Customer':'Gold', 'Companies':['Gold Ltd', 'Gold X', 'Gold De'], '
df = pd.DataFrame(columns=['Customer','Companies', 'Date'])
df = df.append({'Customer':'Gold', 'Companies':['Gold Ltd', 'Gold X', 'Gold De'], 'Date':'2019-01-07'}, ignore_index=True)
df = df.append({'Customer':'Micro', 'Companies':['Microf', 'Micro Inc', 'Micre'], 'Date':'2019-02-10'}, ignore_index=True)
Customer Companies Date
0 Gold [Gold Ltd, Gold X, Gold De] 2019-01-07
1 Micro [Microf, Micro Inc, Micre] 2019-02-10
df2 = pd.DataFrame(columns=['Companies', 'Date'])
df2 = df2.append({'Companies':'Gold Ltd', 'Date':'2019-01-01'}, ignore_index=True)
df2 = df2.append({'Companies':'Gold X', 'Date':'2020-01-07'}, ignore_index=True)
df2 = df2.append({'Companies': 'Gold De', 'Date':'2018-07-07'}, ignore_index=True)
df2 = df2.append({'Companies':'Microf', 'Date':'2019-02-18'}, ignore_index=True)
df2 = df2.append({'Companies':'Micro Inc', 'Date':'2017-09-27'}, ignore_index=True)
df2 = df2.append({'Companies':'Micre', 'Date':'2018-12-11'}, ignore_index=True)
Companies Date
0 Gold Ltd 2019-01-01
1 Gold X 2020-01-07
2 Gold De 2018-07-07
3 Microf 2019-02-18
4 Micro Inc 2017-09-27
5 Micre 2018-12-11
def match_it(d1, d2):
for companies in d1['Companies']:
for company in companies:
if d2['Companies'].str.contains(company).any():
mask = d1.Companies.apply(lambda x: company in x)
dff = d1[mask]
date1 = datetime.strptime(dff['Date'].values[0], '%Y-%m-%d').date()
date2 = datetime.strptime(d2[d2['Companies']==company]['Date'].values[0], '%Y-%m-%d').date()
if date2 < date1:
print(d2[d2['Companies']==company])
new_row = pd.Series([d2[d2['Companies']==company]['Date'], d2[d2['Companies']==company]['Companies']])
return new_row
从更泛泛的方式开始,转换两个数据帧中的日期列 从字符串do datetime: 然后进行如下操作:
df3 = df.explode('Companies')
df3 = df3.merge(df2, on='Companies', suffixes=('_x', ''))
df3 = df3[df3.Date_x > df3.Date].drop(columns='Date_x')
df3.rename(columns={'Companies': 'Name'}, inplace=True)
df3['idx'] = df3.groupby('Customer').cumcount()
df3 = df3.pivot(index='Customer',columns='idx')
df3 = df3.swaplevel(axis=1)
df3 = df3.sort_index(axis=1, ascending=[True, False])
cols = []
for i in range(1, df3.columns.size // 2 + 1):
cols.extend(['Name_' + str(i), 'Date_' + str(i)])
df3.columns = cols
result = df.merge(df3, how='left', left_on='Customer', right_index=True)
结果正是你想要的
要了解详细信息,请分别运行每条指令并打印结果。
与其阅读描述,不如自己看结果
注意:Explode是在Pandas版本中添加的一个相对较新的功能
0.25. 如果您有较旧版本的Pandas,请从升级开始
从03:25:19Z开始编辑以下注释
df1可以有更多的列
为了测试它,我在df1中添加了Xxx列。
在这种情况下,唯一需要的更改是阻止这些附加列
从复制到df3。为此,第一条指令应附加以下内容:
.drop(columns=['Xxx'])
一般情况下,将“Xxx”替换为实际的附加列列表
为了检查不同输出列数的情况,我更改了日期
对于df2至2019-01-06中的Gold X公司,该公司将
也可以包含在输出中
对于您的数据,通过上述更改,结果是:
Customer Companies Date Xxx Name_1 Date_1 Name_2 Date_2 Name_3 Date_3
0 Gold [Gold Ltd, Gold X, Gold De] 2019-01-07 Xxx1 Gold Ltd 2019-01-01 Gold X 2019-01-06 Gold De 2018-07-07
1 Micro [Microf, Micro Inc, Micre] 2019-02-10 Xxx2 Micro Inc 2017-09-27 Micre 2018-12-11 NaN NaT
如你所见:
结果还包括添加的列Xxx。
输出还包含Name_3和Date_3列。
对于df1的第二行,只找到了2个匹配项,
这些列在这里包含NaN和NaT对应项
没有。
据我所知,公司名单可能有不同的长度。在这种情况下应该是什么?您将有不同数量的列。我认为这个问题与您的问题非常相似:如果df2.companys在df.companys中,您希望合并数据帧。如果日期不在第二个日期之后,您将有一些额外的逻辑在输出df中删除列。哇,这是一个很好的答案,谢谢!只有一个问题,如果第一个数据帧有更多的列怎么办?在添加“名称”和“日期”列时,是否有办法保留这些内容?
.drop(columns=['Xxx'])
Customer Companies Date Xxx Name_1 Date_1 Name_2 Date_2 Name_3 Date_3
0 Gold [Gold Ltd, Gold X, Gold De] 2019-01-07 Xxx1 Gold Ltd 2019-01-01 Gold X 2019-01-06 Gold De 2018-07-07
1 Micro [Microf, Micro Inc, Micre] 2019-02-10 Xxx2 Micro Inc 2017-09-27 Micre 2018-12-11 NaN NaT