在Pandas DataFrame的数学运算中为处理函数分配NaN的问题

0 投票
1 回答
37 浏览
提问于 2025-04-12 20:16

我在使用Python的Pandas库处理数据时遇到了一个问题,主要是在进行数学运算时出现了NaN(不是一个数字)的情况。我有一个函数叫做process_mr,它的目的是处理数据框中每个方程列里指定的数学规则。例如,一个数学规则可能是“A = B + C + D”,这里的A、B、C和D都是数据框中的列名,而这个操作是加法。

这个process_mr函数应该遍历数据框,计算每一行的数学表达式,并把结果存储在两个不同的数据框里:subtraction_df用来存放减法结果,boolean_df用来存放布尔值的评估结果。

以下是相关的代码部分:

# Function to perform mathematical operations on DataFrame columns
def process_mr(df, equation_column, subtraction_df, boolean_df):
    if ' = ' in equation_column:
        equation_column2 = equation_column.replace(' = ',' == ')
        lhs, rhs = equation_column2.split('==')
    elif '<=' in equation_column:
        equation_column2 = equation_column
        lhs, rhs = equation_column2.split('<=')
    elif '>=' in equation_column:
        equation_column2 = equation_column
        lhs, rhs = equation_column.split('>=')
    
    for index, row in df.iterrows():
        lhs_list = [x.strip() for x in lhs.split('+')] if '+' in lhs else lhs.split()
        rhs_list = [x.strip() for x in rhs.split('+')] if '+' in rhs else rhs.split()

        # Insert DataFrame values into lhs_list and rhs_list
        lhs_val_list = [row.loc[col] if col != '100' else 100 for col in lhs_list] 
        rhs_val_list = [row.loc[col] if col != '100' else 100 for col in rhs_list]

        # Convert all elements to float
        lhs_val_list = [float(x) for x in lhs_val_list] 
        rhs_val_list = [float(x) for x in rhs_val_list]

        if (np.all(np.isnan(lhs_val_list))) or (all(x is None for x in lhs_val_list)) or (np.all(np.isnan(rhs_val_list)) or (all(x is None for x in rhs_val_list))):
            # Assign NaN where a Math Check would have been performed
            subtraction_df[equation_column][index] = np.nan
            boolean_df[equation_column][index] = np.nan
            continue  # Skips to next iteration
        else:
            # Assign 0 to any NaNs that exist for lhs_val_list and rhs_val_list (NaN can't be used in     a calculation)
            lhs_val_list = [x if not np.isnan(x) else 0 for x in lhs_val_list]
            rhs_val_list = [x if not np.isnan(x) else 0 for x in rhs_val_list]
            # Perform subtraction operation for math rule and assign the result in subtraction_df
            subtraction_df[equation_column][index] = np.sum(lhs_val_list) - np.sum(rhs_val_list)

            # Evaluate math rule and store the result in boolean_df
            row_vals = df.loc[index]
            boolean_df[equation_column][index] = eval(equation_column2, row_vals.to_dict())

    return subtraction_df, boolean_df

# Loop through equation columns and perform the operation
for col in new_mr_columns_list:
    process_mr(df, col, subtraction_df, boolean_df)

使用上面的函数和代码,我原本希望在boolean_df中由于在评估之前进行了NaN的赋值,能产生更少的假值(False)。然而,结果却是产生了比我预期的更多的假值。你能看到代码中有什么错误或问题吗?谢谢。

1 个回答

0

这里有一些一般性的建议:

  • 尽量使用 .iat.at,而不是 .loc,这样会更快。这里有个链接可以了解更多关于这个的内容:点击这里
  • 在循环中使用 eval 来评估布尔表达式可能会有风险,而且效率不高。建议你换个方法。
  • 我觉得你可以简化你的代码,现在的代码中有太多的列表推导式,这样会让代码变得复杂,也更容易出错。

撰写回答