基于条件从Pandas DataFrame关联Number与最近Capital标签
解决方法:将Number行关联到最近的Capital行
嘿,我来帮你搞定这个把Number行关联到最近Capital行的问题~首先先修正你现有代码里的一个小错误:你在筛选Country行的时候写了df[1],这是按位置取列,但你的列名是Label,应该改成df['Label'],否则会报错哦。
接下来,我给你两种高效的实现方式,都能满足你的需求:
方法一:用merge_asof快速匹配(推荐)
Pandas的merge_asof是专门用来按顺序匹配最近行的工具,非常适合你的场景。它会根据指定的键(这里用文本位置的StartID),为每个Number行找到最近的Capital行。
import pandas as pd # 读取数据(和你的代码一致,修正了Country筛选的错误) columnsName =['Token', 'Label', 'StartID', 'EndID'] df = pd.read_csv('resources/testcsv.csv', index_col=0, skip_blank_lines=True, header=0) # 筛选出Number和Capital行,并保留原索引 df_numbers = df[df['Label'].str.lower() == 'number'].reset_index().rename(columns={'index': 'Number_原索引'}) df_capitals = df[df['Label'].str.lower() == 'capital'].reset_index().rename(columns={'index': 'Capital_原索引'}) # merge_asof要求匹配的键必须是排序好的,所以先按StartID排序 df_numbers_sorted = df_numbers.sort_values('StartID') df_capitals_sorted = df_capitals.sort_values('StartID') # 匹配最近的Capital行,direction='nearest'表示找前后最接近的 merged_result = pd.merge_asof( df_numbers_sorted, df_capitals_sorted, on='StartID', direction='nearest' ) # 展示关键结果:Number行和对应的Capital行信息 print(merged_result[['Number_原索引', 'Token_x', 'Label_x', 'Capital_原索引', 'Token_y', 'Label_y']])
运行后你会得到这样的结果:
Number_原索引 Token_x Label_x Capital_原索引 Token_y Label_y 0 3 four million Number 1 Berlin Capital 1 6 ten million Number 7 London Capital
完全符合你想要的关联:第3行(four million)关联到第1行(Berlin),第6行(ten million)关联到第7行(London)。
如果只想匹配当前Number行之前的最近Capital,把direction='nearest'改成direction='backward';如果只想匹配之后的,改成direction='forward'即可。
方法二:手动遍历匹配(适合理解逻辑)
如果你想更直观地理解匹配过程,可以手动遍历每个Number行,计算它和所有Capital行的位置差,找到最近的那个:
import pandas as pd # 读取数据(同样修正了Country筛选的错误) columnsName =['Token', 'Label', 'StartID', 'EndID'] df = pd.read_csv('resources/testcsv.csv', index_col=0, skip_blank_lines=True, header=0) # 筛选Number和Capital行 df_numbers = df[df['Label'].str.lower() == 'number'] df_capitals = df[df['Label'].str.lower() == 'capital'] # 提取Capital行的索引和StartID,方便后续计算 capital_indices = df_capitals.index.tolist() capital_starts = df_capitals['StartID'].tolist() # 逐个处理每个Number行 match_results = [] for num_idx, num_row in df_numbers.iterrows(): num_start = num_row['StartID'] # 计算当前Number行与每个Capital行的位置差绝对值 distance = [abs(num_start - cap_start) for cap_start in capital_starts] # 找到距离最小的Capital行的索引 closest_cap_idx = capital_indices[distance.index(min(distance))] closest_cap_row = df.loc[closest_cap_idx] # 保存匹配结果 match_results.append({ 'Number_原索引': num_idx, 'Number_Token': num_row['Token'], 'Capital_原索引': closest_cap_idx, 'Capital_Token': closest_cap_row['Token'] }) # 转成DataFrame查看结果 result_df = pd.DataFrame(match_results) print(result_df)
这个方法的结果和第一种完全一致,适合用来理解背后的匹配逻辑。
内容的提问来源于stack exchange,提问作者Betafish
相关产品推荐
相关产品推荐

