我有两个数据框:
df1 = pd.DataFrame([[set(['foo', 'baz'])],
[set(['bar', 'baz'])]], columns=['items'])
items
0 {foo, baz}
1 {bar, baz}
df2 = pd.DataFrame([[set(['bar', 'baz', 'foo']), 1],
[set(['bar', 'baz', 'foo']), 2],
[set(['bar', 'baz', 'foo']), 3],
[set(['one', 'two', 'bar']), 2]], columns=['items', 'other'])
items other
0 {foo, bar, baz} 1
1 {foo, bar, baz} 2
2 {foo, bar, baz} 3
3 {two, one, bar} 2
目标是将df2
与df1
连接,其中df1.items
中的值是df2.items
的子集。这两列都是set()
对于上下文,这是在实施apriori算法之后将关联规则与客户购买结合在一起。
添加预期输出:
df3 = pd.DataFrame([[[set(['foo', 'baz'])], set(['bar', 'baz', 'foo']), 1],
[[set(['foo', 'baz'])], set(['bar', 'baz', 'foo']), 2],
[[set(['foo', 'baz'])], set(['bar', 'baz', 'foo']), 3],
[[set(['bar', 'baz'])], None, None]], columns=['items', 'items', 'other'])
items items other
0 [{foo, baz}] {foo, bar, baz} 1.0
1 [{foo, baz}] {foo, bar, baz} 2.0
2 [{foo, baz}] {foo, bar, baz} 3.0
3 [{bar, baz}] None NaN
答案 0 :(得分:1)
创建数据框
import pandas as pd
df1 = pd.DataFrame({'key': [1, 1],
'id': [0, 1],
'items': [set(['foo', 'baz']), set(['bar', 'baz'])]})
df2 = pd.DataFrame({'key': [1, 1, 1, 1],
'items': [set(['bar', 'baz', 'foo']), set(['bar', 'baz', 'foo']), set(['bar', 'baz', 'foo']), set(['one', 'two', 'bar'])],
'other': [1, 2, 3, 2]
})
然后制作笛卡尔积
merged_df = df1.merge(df2, on='key')
merged_df
key id items_x items_y other
0 1 0 {baz, foo} {foo, baz, bar} 1
1 1 0 {baz, foo} {foo, baz, bar} 2
2 1 0 {baz, foo} {foo, baz, bar} 3
3 1 0 {baz, foo} {one, bar, two} 2
4 1 1 {baz, bar} {foo, baz, bar} 1
5 1 1 {baz, bar} {foo, baz, bar} 2
6 1 1 {baz, bar} {foo, baz, bar} 3
7 1 1 {baz, bar} {one, bar, two} 2
定义您的自定义函数,看看它是否在一种情况下有效
def check_if_all_in_list(list1, list2):
return all(elem in list2 for elem in list1)
check_if_all_in_list(merged_df['items_x'][0], merged_df['items_y'][0])
True
创建比赛
merged_df['check'] = merged_df.apply(lambda row: check_if_all_in_list(row['items_x'], row['items_y']), axis=1)
merged_df
key id items_x items_y other check
0 1 0 {baz, foo} {foo, baz, bar} 1 True
1 1 0 {baz, foo} {foo, baz, bar} 2 True
2 1 0 {baz, foo} {foo, baz, bar} 3 True
3 1 0 {baz, foo} {one, bar, two} 2 False
4 1 1 {baz, bar} {foo, baz, bar} 1 True
5 1 1 {baz, bar} {foo, baz, bar} 2 True
6 1 1 {baz, bar} {foo, baz, bar} 3 True
7 1 1 {baz, bar} {one, bar, two} 2 False
现在过滤掉不需要的内容
mask = (merged_df['check']==True)
merged_df[mask]
key id items_x items_y other check
0 1 0 {baz, foo} {foo, baz, bar} 1 True
1 1 0 {baz, foo} {foo, baz, bar} 2 True
2 1 0 {baz, foo} {foo, baz, bar} 3 True
4 1 1 {baz, bar} {foo, baz, bar} 1 True
5 1 1 {baz, bar} {foo, baz, bar} 2 True
6 1 1 {baz, bar} {foo, baz, bar} 3 True
答案 1 :(得分:0)
如果您只想根据条件过滤df2
(有点像select ... from table where X in (select ...)
),则可以执行以下操作:
df2.loc[df2["items"].apply(lambda x: any(el.intersection(x)==el for el in df1["items"].tolist()))]
输出:
items other
0 {foo, baz, bar} 1
1 {foo, baz, bar} 2
2 {foo, baz, bar} 3
要实现类似“左连接”的效果:
import numpy as np
df2["match"]=df2["items"].apply(lambda x: any(el.intersection(x)==el for el in df1["items"].tolist()))
df2.loc[~df2["match"], ["other"]]=np.nan
df2.drop(columns="match", inplace=True)
输出:
items other
0 {bar, baz, foo} 1.0
1 {bar, baz, foo} 2.0
2 {bar, baz, foo} 3.0
3 {two, bar, one} NaN