【问题标题】:Using pandas fillna in the init function of a class python在类python的init函数中使用pandas fillna
【发布时间】:2018-02-18 23:07:15
【问题描述】:

我想定义一个具有 pd.DataFrame 对象的超级类,如下所示:

import pandas as pd

class my_data_frame(pd.DataFrame):
    def __init__(self, index, columns):
        super(my_data_frame,self).__init__(index = index, columns = columns)
        self = self.fillna(0)
        print('init',self)

df = my_data_frame([1,2,3],['a','b','c'])
print('first', df)

这将打印输出

init    a  b  c
1  0  0  0
2  0  0  0
3  0  0  0
first      a    b    c
1  NaN  NaN  NaN
2  NaN  NaN  NaN
3  NaN  NaN  NaN

所以问题是为什么第 5 行的 fillna 函数不起作用。由于从 init 函数打印它似乎有效,但在命令行中却没有。

【问题讨论】:

  • self = self.fillna(0) 只是将一个新的 Dataframe 分配给局部变量 self,然后在方法终止后将其丢弃

标签: python pandas class


【解决方案1】:

@Allen 已经向您展示了这样做的方法,但我会添加一些额外的评论。

  1. subclassing pandas objects阅读此链接

  2. 我会简化对super 的调用以避免fillna 的麻烦

  3. 这是我在第 1 项中使用链接的方式。

    一个。我创建了一个将参数直接传递给 DataFrame 构造函数的类。
    湾。我查看是否通过了data,如果没有,我将其设置为零。
    C。我创建了一个属性 (@property) 来定义构造函数是什么。这就是告诉 pandas 在创建这些新副本时要使用的内容。因为我定义了一个直接传递所有参数的子类,所以这应该很干净。
    d。我定义了一个函数来实现初始化器的意图。


import pandas as pd

class MyDataFrame(pd.DataFrame):
    def __init__(self, *args, **kwargs):

        if len(args) == 0:
            kwargs.setdefault('data', 0)

        super(MyDataFrame, self).__init__(*args, **kwargs)

    @property
    def _constructor(self):
        return MyDataFrame

def my_data_frame(index, columns):
    return MyDataFrame(index=index, columns=columns)

演示

mdf = my_data_frame([1,4,3],['a','b','c'])
mdf

   a  b  c
1  0  0  0
4  0  0  0
3  0  0  0

mdf2 = mdf[['a', 'c']]
mdf2

   a  c
1  0  0
4  0  0
3  0  0

type(mdf2)

__main__.MyDataFrame

【讨论】:

    【解决方案2】:

    出于某种原因使用 inplace = True 有效:

    class my_data_frame(pd.DataFrame):
        def __init__(self, index, columns):
            super(my_data_frame,self).__init__(index = index, columns = columns)
            self.fillna(0, inplace=True)
            print('init',self)
    
    
    my_data_frame([1,4,3],['a','b','c'])
    init    a  b  c
    1  0  0  0
    4  0  0  0
    3  0  0  0
    Out[557]: 
       a  b  c
    1  0  0  0
    4  0  0  0
    3  0  0  0
    

    我认为这与作业有关。当您使用 self= 时,它会创建一个新的 DataFrame 并分配给您的自定义类,但超类未更新。

    【讨论】:

    • 这是因为self = self.fillna(0) 只是为局部变量self 分配了一个新的Dataframe
    【解决方案3】:

    我知道从数据框继承确实很诱人,但不要这样做。这是您将遇到的许多问题之一。最常见的可能是许多函数返回“新鲜”数据帧。因此,您在 new_dataframe 上使用一种方法,它将返回一个正常的数据帧。

    此外,您的示例不会那样工作,因为一旦您分配给 self,python 会将其视为局部变量。

    【讨论】:

      猜你喜欢
      • 2018-08-14
      • 2017-03-19
      • 2018-08-09
      • 2019-07-18
      • 2018-04-26
      • 2015-01-28
      • 1970-01-01
      • 2011-03-21
      • 2021-05-06
      相关资源
      最近更新 更多