如何根据另一DataFrame的年龄区间与国家条件填充pandas DataFrame?
问题解决:根据年龄区间匹配填充DataFrame字段
错误原因
你遇到的index 0 is out of bounds错误,确实是因为当Table2的年龄区间在Table1中没有对应数据时,筛选得到的Marks Series是空的,此时values[0]试图访问空数组的第一个元素,导致索引越界。
解决方案
方案1:修改原有循环,处理空值情况
直接在循环里判断筛选结果是否为空,为空则赋值NaN,否则取第一个值:
import numpy as np for index, row in table2.iterrows(): # 筛选符合条件的Country A分数 filtered_marks = table1[(table1['Country'] == 'A') & (table1['Age'] >= row['Age Band From']) & (table1['Age'] <= row['Age Band To'])]['Marks'] # 赋值:有结果则取第一个,无结果则为NaN table2.loc[index, 'Country A'] = filtered_marks.iloc[0] if not filtered_marks.empty else np.nan # 同理处理Country B filtered_marks_b = table1[(table1['Country'] == 'B') & (table1['Age'] >= row['Age Band From']) & (table1['Age'] <= row['Age Band To'])]['Marks'] table2.loc[index, 'Country B'] = filtered_marks_b.iloc[0] if not filtered_marks_b.empty else np.nan
方案2:使用apply函数简化代码
定义一个通用函数处理匹配逻辑,然后用apply批量处理,比iterrows更高效:
import pandas as pd import numpy as np # 示例数据(替换为你的真实数据即可) table1 = pd.DataFrame({ 'Country': ['A', 'B'], 'Age': [25, 45], 'Marks': [7, 8] }) table2 = pd.DataFrame({ 'Age Band From': [20, 30, 40], 'Age Band To': [29, 39, 49], 'Country A': [np.nan, np.nan, np.nan], 'Country B': [np.nan, np.nan, np.nan] }) # 定义匹配函数 def get_matching_mark(age_low, age_high, target_country): match = table1[(table1['Country'] == target_country) & (table1['Age'] >= age_low) & (table1['Age'] <= age_high)]['Marks'] return match.iloc[0] if not match.empty else np.nan # 批量填充Country A和Country B列 table2['Country A'] = table2.apply(lambda x: get_matching_mark(x['Age Band From'], x['Age Band To'], 'A'), axis=1) table2['Country B'] = table2.apply(lambda x: get_matching_mark(x['Age Band From'], x['Age Band To'], 'B'), axis=1)
执行后得到的table2结果:
| Age Band From | Age Band To | Country A | Country B |
|---|---|---|---|
| 20 | 29 | 7.0 | NaN |
| 30 | 39 | NaN | NaN |
| 40 | 49 | NaN | 8.0 |
方案3:全向量化合并(大数据量推荐)
如果你的数据量较大,推荐用merge实现全向量化操作,避免循环和apply,效率更高:
# 扩展table2和table1,建立交叉关联 table2_expanded = table2[['Age Band From', 'Age Band To']].assign(key=1) table1_expanded = table1.assign(key=1) merged = pd.merge(table2_expanded, table1_expanded, on='key').drop('key', axis=1) # 筛选年龄落在区间内的记录 filtered = merged[(merged['Age'] >= merged['Age Band From']) & (merged['Age'] <= merged['Age Band To'])] # 转成宽格式并合并回原table2 result = table2.merge( filtered.pivot(index=['Age Band From', 'Age Band To'], columns='Country', values='Marks').reset_index(), on=['Age Band From', 'Age Band To'], how='left' ) # 重命名列保持原格式 result.rename(columns={'A': 'Country A', 'B': 'Country B'}, inplace=True)
内容的提问来源于stack exchange,提问作者Rishav Ganguly
相关产品推荐
相关产品推荐

