来自 pandas 数据帧的 Select 行同时来自另一个数据帧中的行的两个值
Select rows from pandas dataframe by two values at the same time from rows in another dataframe
有关于pandas的问题:
我有两个数据框:
df1 = pd.DataFrame({'user_id': ['12', '22', '33', '44'],
'time': ['t1', 't2', 't3', 't4'],
'data': [{'av': '8.0', 'si': 3, 'am' : 2}, {'av': '8.0', 'si': 44}, {'av': '8.0', 'si': 1}, {'av': '8.0', 'si': 22}]})
df2 = pd.DataFrame({'user_id': ['11', '22', '33', '44'],
'time': ['t1', 't2', 't3', 't4'],
'data': [{'cv': 'ff', 'si': 3}, {'cv': 'ff', 'si': 44}, {'cv': 'fa', 'si': 2}, {'cv': 'ff', 'si': 21}]})
并且我需要过滤 df1 以拒绝包含值 'user_id' 和 ['data'] 的行。'si' 与 'user_id' 和 [[=29= 相同]].'si' 来自 df2 行。如果我愿意:
filter1 = df1['data'].str['si'].isin(df2['data'].str['si'])
filter2 = df1['user_id'].isin(df2['user_id'])
df3= df1[filter1 & filter2]
结果无效,因为我需要准确拒绝值满足两个条件的行:
例如 df1
中的第 2 行
user_id time data
22 t2 'av': '8.0', 'si': 44
来自 df2:
user_id time data
22 t2 'cv': 'ff', 'si': 44
非常感谢您的帮助!
规范化数据应该会简化此操作,并且每个潜在的比较都会变得更加容易和清晰。
标准化 + 应用清洁条件:
df1 = pd.concat([df1.drop(columns=['data']), pd.json_normalize(df1.data)], axis=1)
df2 = pd.concat([df2.drop(columns=['data']), pd.json_normalize(df2.data)], axis=1)
现在数据框如下所示:
df1:
user_id
time
av
si
am
0
12
t1
8
3
2
1
22
t2
8
44
nan
2
33
t3
8
1
nan
3
44
t4
8
22
nan
df2:
user_id
time
cv
si
0
11
t1
ff
3
1
22
t2
ff
44
2
33
t3
fa
2
3
44
t4
ff
21
现在您可以将它们合并并使用指示器,如下所示
df1_filtered = df1.merge(df2[['user_id', 'si']], how='outer', indicator=True)
df1_filtered = df1_filtered[df1_filtered._merge.eq('left_only')].drop(columns=['_merge'])
df1_filtered
user_id
time
av
si
am
0
12
t1
8
3
2
2
33
t3
8
1
nan
3
44
t4
8
22
nan
df2_filtered = df2.merge(df1[['user_id', 'si']], how='outer', indicator=True)
df2_filtered = df2_filtered[df2_filtered._merge.eq('left_only')].drop(columns=['_merge'])
print(df2_filtered.to_markdown())
user_id
time
cv
si
0
11
t1
ff
3
2
33
t3
fa
2
3
44
t4
ff
21
有关于pandas的问题:
我有两个数据框:
df1 = pd.DataFrame({'user_id': ['12', '22', '33', '44'],
'time': ['t1', 't2', 't3', 't4'],
'data': [{'av': '8.0', 'si': 3, 'am' : 2}, {'av': '8.0', 'si': 44}, {'av': '8.0', 'si': 1}, {'av': '8.0', 'si': 22}]})
df2 = pd.DataFrame({'user_id': ['11', '22', '33', '44'],
'time': ['t1', 't2', 't3', 't4'],
'data': [{'cv': 'ff', 'si': 3}, {'cv': 'ff', 'si': 44}, {'cv': 'fa', 'si': 2}, {'cv': 'ff', 'si': 21}]})
并且我需要过滤 df1 以拒绝包含值 'user_id' 和 ['data'] 的行。'si' 与 'user_id' 和 [[=29= 相同]].'si' 来自 df2 行。如果我愿意:
filter1 = df1['data'].str['si'].isin(df2['data'].str['si'])
filter2 = df1['user_id'].isin(df2['user_id'])
df3= df1[filter1 & filter2]
结果无效,因为我需要准确拒绝值满足两个条件的行: 例如 df1
中的第 2 行user_id time data
22 t2 'av': '8.0', 'si': 44
来自 df2:
user_id time data
22 t2 'cv': 'ff', 'si': 44
非常感谢您的帮助!
规范化数据应该会简化此操作,并且每个潜在的比较都会变得更加容易和清晰。
标准化 + 应用清洁条件:
df1 = pd.concat([df1.drop(columns=['data']), pd.json_normalize(df1.data)], axis=1)
df2 = pd.concat([df2.drop(columns=['data']), pd.json_normalize(df2.data)], axis=1)
现在数据框如下所示:
df1:
user_id | time | av | si | am | |
---|---|---|---|---|---|
0 | 12 | t1 | 8 | 3 | 2 |
1 | 22 | t2 | 8 | 44 | nan |
2 | 33 | t3 | 8 | 1 | nan |
3 | 44 | t4 | 8 | 22 | nan |
df2:
user_id | time | cv | si | |
---|---|---|---|---|
0 | 11 | t1 | ff | 3 |
1 | 22 | t2 | ff | 44 |
2 | 33 | t3 | fa | 2 |
3 | 44 | t4 | ff | 21 |
现在您可以将它们合并并使用指示器,如下所示
df1_filtered = df1.merge(df2[['user_id', 'si']], how='outer', indicator=True)
df1_filtered = df1_filtered[df1_filtered._merge.eq('left_only')].drop(columns=['_merge'])
df1_filtered
user_id | time | av | si | am | |
---|---|---|---|---|---|
0 | 12 | t1 | 8 | 3 | 2 |
2 | 33 | t3 | 8 | 1 | nan |
3 | 44 | t4 | 8 | 22 | nan |
df2_filtered = df2.merge(df1[['user_id', 'si']], how='outer', indicator=True)
df2_filtered = df2_filtered[df2_filtered._merge.eq('left_only')].drop(columns=['_merge'])
print(df2_filtered.to_markdown())
user_id | time | cv | si | |
---|---|---|---|---|
0 | 11 | t1 | ff | 3 |
2 | 33 | t3 | fa | 2 |
3 | 44 | t4 | ff | 21 |