【问题标题】:how to apply a class function to replace NaN for mean within a subset of pandas df columns?如何应用类函数来替换熊猫 df 列子集中的均值的 NaN?
【发布时间】:2021-11-09 00:20:40
【问题描述】:

该类由一组属性和函数组成,包括:

属性:

  • df : pandas 数据框。
  • numerical_feature_names:具有数值的 df 列。
  • label_column_names:要分组的df字符串列。

功能:

  • mean(nums):将数字列表作为输入并返回平均值
  • fill_na(df, numerical_feature_names, label_columns):将类属性作为输入并返回转换后的 df。

这是课程:


class PLUMBER():
    
    def __init__(self):
        
        ################# attributes ################
        
        self.df=df

        # specify label and numerical features names:
        
        self.numerical_feature_names=numerical_feature_names
        self.label_column_names=label_column_names
        
   
    #####################  mean  ##############################
    
    def mean(self, nums):
        
        total=0.0
        
        for num in nums:
            total=total+num
            
        return total/len(nums)
    

   ############ fill the numerical features ##################
   
    def fill_na(self, df, numerical_feature_names, label_column_names):
        
        # declaring parameters:
        df=self.df
        numerical_feature_names=self.numerical_feature_names
        label_column_names=self.label_column_names
        
        # now replacing NaN with group mean
        
        for numerical_feature_name in numerical_feature_names:
            
            df[numerical_feature_name]=df.groupby([label_column_names]).transform(lambda x: x.fillna(self.mean(x)))
        
            
        return df

当尝试将它应用到 pandas df 时:

if __name__=="__main__":
    
    # initialize class
    plumber=PLUMBER()
    
    # replace NaN with group mean
    df=plumber.fill_na(df=df, numerical_feature_names=numerical_feature_names, label_column_names=label_column_names)
  

出现下一个错误:

ValueError: Grouper 和轴必须是相同的长度

数据和类参数

import pandas as pd

d={'month': ['01/01/2020', '01/02/2020', '01/03/2020', '01/01/2020', '01/02/2020', '01/03/2020'], 
   'country': ['Japan', 'Japan', 'Japan', 'Poland', 'Poland', 'Poland'], 
   'level':['A01', 'A01', 'A01', 'A00','A00', 'A00'],
   'job title':['Insights Manager', 'Insights Manager', 'Insights Manager', 'Sales Director', 'Sales Director', 'Sales Director'],
   'number':[np.nan, 450, 299, np.nan, 19, 29],
   'age':[np.nan, 30, 28, np.nan, 29, 18]}

df=pd.DataFrame(d)


# headers
column_names=df.columns.values.tolist()
column_names= [column_name.strip() for column_name in column_names]


# label_column_names (to be grouped)
label_column_names=['country', 'level', 'job title']


# numerical_features:
numerical_feature_names = [x for x in column_names if x not in label_column_names]
numerical_feature_names.remove('month')

如何更改类以获得转换后的 df(即用它的组平均值替换 np.nan 的那个)?

【问题讨论】:

    标签: python pandas dataframe oop machine-learning


    【解决方案1】:

    首先错误是因为label_column_names 已经是list,所以在groupby 中你不需要[] 围绕它。所以应该是df.groupby(label_column_names)... 而不是df.groupby([label_column_names])...

    现在,为了真正解决你的问题,在你的类的函数 fill_na 中,将循环 for(你实际上不需要它)替换为

    df[numerical_feature_names] = (
        df[numerical_feature_names]
          .fillna(
              df.groupby(label_column_names)
                [numerical_feature_names].transform('mean')
          )
    )
    

    您在其中fillnanumerical_feature_names 通过groupy.tranform 与这些列的mean 的结果

    【讨论】:

    • 感谢@Ben.T! 的观察,此外,为了从类中调用均值函数,是否可以在transform() 中应用lambda,或者最好只调用@ 987654336@里面?
    • @AlvaroMartinez 确定您可以使用transform(lambda x: x.mean()),但使用transform('mean') 可能比lambda 的相同结果更快。很难测试,但如果你有大数据帧,它可以显示一些时间差来计算结果
    • @AlvaroMartinez 所以你的mean 版本的问题不能很好地处理nan(至少不是你想要的用途)因此self.mean 的结果将永远是@ 987654343@ 如果在组中有nan。所以使用你的版本的快速修复是在循环中for num in nums: ,做if num == num: total=total+num(这是一种不对nans 值求和的方法。然后做transform(lambda x: self.mean(x)) 应该可以工作
    猜你喜欢
    • 2021-11-10
    • 2020-10-27
    • 2018-12-02
    • 2018-03-16
    • 2019-04-24
    • 2021-06-19
    • 1970-01-01
    • 2015-10-12
    • 2018-08-24
    相关资源
    最近更新 更多