混合类型DataFrame列除法运算:保留特殊字符串值的实现方案
处理带特殊标记的DataFrame列计算
输入示例DataFrame
Year Grade3MathPass Grade3MathTest Grade4MathPass Grade4MathTest 0 2019 1 2020 *** 15 5 15 2 2021 *** *** 12 3 2022 3 10 4 10
计算规则
- 两列均为数字时,返回保留5位小数的结果;
- 任意一列含
***(样本量不足),返回NA; - Pass列为空白(表示0人通过),返回
0; - 两列均空白(无学生测试/通过),返回
None。
期望输出
Year Grade3MathPass Grade3MathTest Grade3Average Grade4MathPass Grade4MathTest Grade4Average 2019 None 2020 *** 15 NA 5 15 0.33333 2021 *** *** NA 12 0 2022 3 10 0.30000 4 10 0.40000
可行解决方案
针对数百列的场景,通过自定义判断函数+自动列匹配的方式实现,无需手动处理每一列:
代码实现
import pandas as pd # 构建示例数据(实际场景可直接读取你的数据源) data = { 'Year': [2019, 2020, 2021, 2022], 'Grade3MathPass': ['', '***', '***', '3'], 'Grade3MathTest': ['', '15', '***', '10'], 'Grade4MathPass': ['', '5', '', '4'], 'Grade4MathTest': ['', '15', '12', '10'] } df = pd.DataFrame(data) # 核心计算函数,严格匹配规则 def calc_avg(pass_val, test_val): # 规则2:含***则返回NA if pass_val == '***' or test_val == '***': return 'NA' # 提取空白/空值状态 pass_empty = pd.isna(pass_val) or pass_val == '' test_empty = pd.isna(test_val) or test_val == '' # 规则4:两列均空白返回None if pass_empty and test_empty: return 'None' # 规则3:仅Pass列空白返回0 if pass_empty: return '0' # 规则1:数值计算,保留5位小数 try: pass_num = float(pass_val) test_num = float(test_val) # 额外处理除数为0的情况(按需调整) if test_num == 0: return 'NA' return round(pass_num / test_num, 5) # 捕获其他转换异常,返回NA except: return 'NA' # 自动匹配Pass和Test列对(按列名前缀关联) pass_cols = [col for col in df.columns if 'Pass' in col] col_pairs = [] for col in pass_cols: test_col = col.replace('Pass', 'Test') if test_col in df.columns: col_pairs.append((col, test_col)) # 批量计算并添加新列 for pass_col, test_col in col_pairs: avg_col = pass_col.replace('Pass', 'Average') df[avg_col] = df.apply(lambda row: calc_avg(row[pass_col], row[test_col]), axis=1) # 查看结果 print(df.to_string(index=False))
方案优势
- 自动化列匹配:无需手动指定数百列的对应关系,通过列名规则自动关联Pass和Test列;
- 规则全覆盖:自定义函数依次判断所有特殊场景,优先级清晰,避免逻辑冲突;
- 保留原标记:全程保留
***、空白等特殊标记,不会丢失业务含义; - 异常处理:通过
try-except捕获数值转换异常,避免程序崩溃。
内容的提问来源于stack exchange,提问作者eton blue
相关产品推荐
相关产品推荐

