Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/blackberry/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 迭代dataframe列中的列表元素,并与不同dataframe中的值匹配_Python_Pandas - Fatal编程技术网

Python 迭代dataframe列中的列表元素,并与不同dataframe中的值匹配

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'], '

我有两个数据帧,我希望迭代companys列中每个列表中的元素,并且仅当第一个数据帧的日期出现在第二个数据帧的日期之后时,才将其与第二个数据帧中的公司名称相匹配。我需要两列作为名称匹配项,两列作为返回的日期匹配项

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