python - 连接两个数据框,其中列值(一组)是另一个数据框的子集
问题描述
我有两个数据框:
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()
就上下文而言,这是在实施先验算法后将关联规则与客户购买结合起来。
添加预期输出:
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
解决方案
创建你的数据框
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
推荐阅读
- java - 如何做一个子列表引用他原来的ArrayList?
- javascript - 需要使用 onclick 事件重新启用禁用的 onmouseon
- neo4j - 用于链接的 Neo4j 查询,“编织”模式
- angular - Angular 表单 - 如何绑定 formControlName 以在 formArrayName 中选择以使用对象
- javascript - javascript 正则表达式查询的所有实例,其中字符匹配是可重复的
- sql - 为什么选择更新仅适用于版本化实体?
- javascript - Javascript + 从变量名和字符串构建动态变量名
- java - 为什么 AspectJ 会生成一个空的 Annotation 检查?
- java - 在 libgdx 中绘制 3d 场景背后的舞台
- java - buildConfigField 无法从 gradle.properties 恢复我的 api 密钥