假设我有 2 个数据框,其中有 3 个公共标识列。
dataframe1
id1 id2 id3 value1 value2 value3
1001 9001 3001 blue square true
1005 9001 3001 yellow circle false
1009 2001 3001 black rectangle true
1010 9001 5001 blue star false
dataframe2
id1 id2 id3 valuex valuey valuez
1001 9001 3001 1000 2.5 5
1001 null null 200 1.0 3
null 9001 null 200 5.4 0
null 9001 3001 1000 3.5 6
1001 9001 null 1001 4.5 7
1001 null 3001 1001 4.5 7
在此示例中,我可以将 dataframe1 中的一行与 dataframe2 中的多行进行匹配。我想根据匹配的列分配排名,并使用最高排名加入。
我想根据排名加入dataframe1和dataframe2,在id列id1、id2和id3之间,如果3列匹配,我想考虑最高排名并加入并忽略与id1和id2或id2和id3等匹配的其他行.,如果 3 列不匹配,我想考虑 2 个 id 列匹配的行并确定优先级 - 比如说,如果有 2 行有 2 个 id 匹配,如 id1 和 id2、id2 和 id3,我想优先考虑 id2 和 id3 (意味着会获得更高的排名)。
我该怎么办?我更喜欢使用函数来计算排名,以便我可以实现复杂的逻辑。
import pandas as pd
df1 = pd.DataFrame(
{
"id1": [1001, 1005, 1009, 1010],
"id2": [9001, 9001, 2001, 9001],
"id3": [3001, 3001, 3001, 5001],
"value1": ["blue", "yellow", "black", "blue"],
"value2": ["square", "circle", "rectangle", "star"],
"value3": [True, False, True, False],
}
)
df2 = pd.DataFrame(
{
"id1": [1001, 1001, None, None, 1001, 1001],
"id2": [9001, None, 9001, 9001, 9001, None],
"id3": [3001, None, None, 3001, None, 3001],
"valuex": [1000, 200, 200, 1000, 1001, 1001],
"valuey": [2.5, 1.0, 5.4, 3.5, 4.5, 4.5],
"valuez": [5, 3, 0, 6, 7, 7],
}
)
for col in ["id1", "id2", "id3"]:
df2[col] = df2[col].astype("Int64")
df3 = pd.merge(df1, df2, how="cross")
df3["num_matches"] = df3.apply(
lambda row: sum(
[(row[f"id{i}_x"] == row[f"id{i}_y"]) is True for i in range(1, 4)]
),
axis=1,
)
df3.sort_values("num_matches", ascending=False, inplace=True)
df3.drop_duplicates(
subset=["id1_x", "id2_x", "id3_x"],
keep="first",
inplace=True,
)
print(df3)
产生
id1_x id2_x id3_x value1 value2 value3 id1_y id2_y id3_y valuex valuey valuez num_matches
0 1001 9001 3001 blue square True 1001 9001 3001 1000 2.5 5 3
6 1005 9001 3001 yellow circle False 1001 9001 3001 1000 2.5 5 2
15 1009 2001 3001 black rectangle True <NA> 9001 3001 1000 3.5 6 1
22 1010 9001 5001 blue star False 1001 9001 <NA> 1001 4.5 7 1