DataFrame中Score与Score2列范围匹配:df.eq(s)失效的解决问询
数值匹配范围字符串并生成目标DataFrame
问题背景
现有存储范围规则的基准DataFrame:
import pandas as pd df = pd.DataFrame({ 'Score': ['>285', '285-280', '280-275', '275-260', '<260'], 'Grade1': ['A1', 'A2', 'A3', 'A4', 'A5'], 'Score2': ['>270', '270-260', '260-250', '250-200', '<200'], 'Grade3': ['D1', 'D2', 'D3', 'D4', 'D5'], 'Grade4': ['ID1', 'ID2', 'ID3', 'ID4', 'ID5'] })
输入包含具体数值和等级的DataFrame:
df_input = pd.DataFrame({ 'Score': [290], 'Grade1': ['A1'], 'Score2': [190], 'Grade3': ['D3'], 'Grade4': ['ID2'] })
直接使用df.eq(df_input.loc[0])无法将数值匹配到对应的范围行,需要自定义逻辑实现匹配并生成目标输出。
解决方案
1. 定义范围匹配函数
编写函数判断单个数值是否符合某条范围字符串的规则:
def match_range(val, range_str): if not pd.isna(val): val = float(val) # 处理大于阈值的情况 if range_str.startswith('>'): threshold = float(range_str[1:]) return val > threshold # 处理小于阈值的情况 elif range_str.startswith('<'): threshold = float(range_str[1:]) return val < threshold # 处理区间范围(格式为"上限-下限") elif '-' in range_str: upper, lower = map(float, range_str.split('-')) return lower <= val <= upper return False
2. 生成完整匹配掩码
对Score、Score2列用自定义函数匹配,其余等级列直接用等值匹配:
s = df_input.loc[0] mask = pd.DataFrame(index=df.index) # 处理范围类型列 mask['Score'] = df['Score'].apply(lambda x: match_range(s['Score'], x)) mask['Score2'] = df['Score2'].apply(lambda x: match_range(s['Score2'], x)) # 处理普通等级列 for col in ['Grade1', 'Grade3', 'Grade4']: mask[col] = df[col].eq(s[col])
生成的掩码与预期一致:
print(mask.to_dict()) # 输出: # {'Score': {0: True, 1: False, 2: False, 3: False, 4: False}, # 'Score2': {0: False, 1: False, 2: False, 3: False, 4: True}, # 'Grade1': {0: False, 1: False, 2: False, 3: False, 4: True}, # 'Grade3': {0: False, 1: False, 2: True, 3: False, 4: False}, # 'Grade4': {0: False, 1: True, 2: False, 3: False, 4: False}}
3. 构建目标输出DataFrame
根据掩码把输入值填充到对应位置,其余位置填空字符串,再添加Tiers列:
df_output = pd.DataFrame(index=df.index) df_output['Tiers'] = df.index + 1 # 生成1-5的层级 # 填充各列数据 for col in mask.columns: df_output[col] = mask[col].apply(lambda x: s[col] if x else '') # 转换为字典格式(与预期输出一致) print(df_output.to_dict())
最终输出完全符合预期:
# {'Tiers': {0: 1, 1: 2, 2: 3, 3: 4, 4: 5}, # 'Score': {0: 290, 1: '', 2: '', 3: '', 4: ''}, # 'Score2': {0: '', 1: '', 2: '', 3: '', 4: 190}, # 'Grade1': {0: '', 1: '', 2: '', 3: '', 4: 'A1'}, # 'Grade3': {0: '', 1: '', 2: 'D3', 3: '', 4: ''}, # 'Grade4': {0: '', 1: 'ID2', 2: '', 3: '', 4: ''}}
内容的提问来源于stack exchange,提问作者Swetha
相关产品推荐
相关产品推荐

