重构使用pandas数据帧的python函数

时间:2018-10-02 16:24:18

标签: python pandas dataframe

我输入了20+的代码,并且肯定会出现以下代码段,在该代码段中,我几乎总是具有相同的代码模式,本质上是(数字对应于以下代码段中的注释):

  1. 计算一个依赖于df几列的测试,该测试可以对任何列进行乘法,除法,加法,任何运算,并用nan替换inf。
  2. 获取所有非南的面具
  3. 使用遮罩创建有效的df
  4. 创建一个新列,将'_mod'添加到所考虑的原始列中,并用某些内容填充
  5. 使用先前在3中创建的有效df,用另一个公式填充“ _mod”列中的其余值,就像在第1步中可以对任何列进行任何操作一样

    摘要

    # col1
    logger.info('col1')
    # 1
    col1_test = (df["colX"] / df["colZ"] / df["colY"] / df["colX"]).replace([np.inf, -np.inf], np.nan)
    # 2
    col1_mask = (~pd.isna(col1_test))
    # 3
    col1_valid = df[col1_mask]
    # 4
    df['col1_mod'] = np.nan
    # 5
    df.loc[col1_mask, 'col1_mod'] = (col1_valid["colX"] - col1_valid["colZ"]) / col1_valid[
        "colY"]
    
    # col2
    logger.info('col2')
    col2_test = (df["colA"] / df["colY"] / df["colA"]).replace(
        [np.inf, -np.inf], np.nan)
    col2_mask = (~pd.isna(col2_test))
    col2_valid = df[col2_mask]
    df['col2_mod'] = 0.0
    df.loc[col2_mask, 'col2_mod'] = col2_valid["colA"] / col2_valid["colY"]
    

    到目前为止,我写的用于重构的内容如下。 但是我想这可能会更进一步,尤其是注释(# df.loc[mask, f'{oldcol}_mod'] = ...)阻塞了它,如果函数返回df本身,则可以解决整个问题。但是,我看不到如何将操作列表作为参数传递给使用在重构函数本身中创建的(valid)的重构函数。

    def refactored(df, oldcol, dftest, replace):
        logger.info(oldcol)
        test = dftest.replace([np.inf, -np.inf], np.nan)
        mask = (~pd.isna(test))
        valid = df[mask]
        df[f'{oldcol}_mod'] = replace
        # df.loc[mask, f'{oldcol}_mod'] = ...
        return valid, mask
    
    
    col1_valid, col1_mask = refactored(df, 'col1', df["colX"] / df["colZ"] / df["colY"] / df["colX"], np.nan)
    df.loc[col1_mask, 'col1_mod'] = (col1_valid["colX"] - col1_valid["colZ"]) / col1_valid["colY"]
    col2_valid, col2_mask = refactored(df, 'col2',df["colA"] / df["colY"] / df["colA"] , 0.0)
    df.loc[col2_mask, 'col2_mod'] = col2_valid["colA"] / col2_valid["colY"]
    

1 个答案:

答案 0 :(得分:1)

考虑将pd.DataFrame.evalpd.DataFrame.pipe结合使用:

def refactored(df, oldcol, dftest, replace, mod_col, series_col):
    # ...some logic...
    test = df.eval(dftest).replace([np.inf, -np.inf], np.nan)
    # ... some more logic...
    df.loc[mask, mod_col] = df.eval(series_col)
    return df

df = df.pipe(refactored, 'col1', 'colX / colZ / colY / colX', np.nan,
             'col1_mod', '(colX - colZ) / colY')\
       .pipe(refactored, 'col2', 'colA / colY / colA', 0.0,
             'col2_mod', 'colA / colY')

通常,您永远不需要将 series 作为函数参数传递。