2

我正在构建一个粒子过滤器来处理来自 pandas DataFrame 的数据。过滤器背后的一个想法是迭代以估计最佳结果(类似于蒙特卡洛)。我有一个基类ExperimentalData(),它具有收集数据等的基本方法。我将构建另一个具有不同过滤器的类。过滤器的类总是派生自ExperimentalData().

在我的内部,我class ParFilter(ExperimentalData)def particleFilter(self, N=1000)运行过滤器并获得所需估计的方法。由于我需要在迭代期间访问数据,因此我在内部构建class Iterator(object)了要处理数据的位置。

我在将数据传递到 class 时遇到问题Iterator()。我尝试大多数情况下我认为应该工作但有AttributeError: 'Iterator' object has no attribute 'myData'. 最终我能够传递一些数据,但它与我期望的数据对象不同。

我的代码简化以说明示例:

import numpy as np
import pandas as pd

class ExperimentalData(object):
    def __init__(self):
        self.xTrueSource = 100
        self.yTrueSource = -7
        print 'source %s  %s' % (self.xTrueSource,self.yTrueSource)
        xSampPoints = np.arange(0,200)
        yTrueSignal = 100/(np.sqrt((self.xTrueSource - xSampPoints)**2 + (self.yTrueSource)**2))
        ySampPoints = yTrueSignal+np.random.randn(200)
        self.myData = pd.DataFrame({'x':xSampPoints,'ySamp':ySampPoints,'yTrue':yTrueSignal})
        #print self.myData
    def __str__(self, rows=2):           
        dfPrintStart = (self.myData[:rows]).to_string()
        dfPrintEnd =(self.myData[-rows:]).to_string()
        stringToPrint='\nPRINTNG INITIAL DATAFRAME FIRST %d ROWS and LAST %d ROWS \n %s\n...\n%s\n'\
                        % (rows, rows, dfPrintStart, dfPrintEnd)
        return stringToPrint

class ParFilter(ExperimentalData):

    def particleFilter(self, N=1000):
        '''function runs particle filter'''
        class Iterator(object):
            def __init__(self):
                '''initialise all values for iteration'''
                self.iteration = 0
                frameToWork = ParFilter().myData                
                print 'FROM CLASS Iterator.__init__ \n%s' % frameToWork
            def iterate(self):
                '''performing one step at the time'''
                self.iteration += 1
                print self.iteration
        myPartFilter = Iterator()
        for n in range(N):
            myPartFilter.iterate()
        return myPartFilter

if __name__ == '__main__':
    data = ParFilter()
    print data
    data.particleFilter(10)

问题是,当我初始化我的类时,我有具有特定值的 dataFrame,但是当我执行以下步骤时:我frameToWork = ParFilter().myData不是采用相同的数据对象,而是生成具有不同数据的新对象。输出快照:

PRINTNG INITIAL DATAFRAME FIRST 2 ROWS and LAST 2 ROWS 
   x     ySamp     yTrue
0  0  0.510414  0.997559
1  1  1.522934  1.007585
...
       x     ySamp     yTrue
198  198  1.508216  1.017815
199  199  2.409181  1.007585

FROM CLASS Iterator.__init__ 
   x     ySamp     yTrue
0  0  0.727060  0.997559
1  1  0.631976  1.007585

in 初始化的第一个值ySamp是 0.510414,它应该与 in 相同,Iterator而不是 0.727060。所以我创建了新对象。

我无法弄清楚如何将原始myData对象放入Iterator我尝试:

    class Iterator(ParFilter):
        def __init__(self):
            '''initialise all values for iteration'''
            self.iteration = 0
            frameToWork = self.myData 

AttributeError: 'Iterator' object has no attribute 'myData'.

我尝试:class Iterator(self.ParFilter)AttributeError: 'ParFilter' object has no attribute 'ParFilter'更多但没有结果。

(我必须使用 pandas DataFrame,因为我的基类非常大,并且得到的 dataFrame 不像示例中那样大)

4

1 回答 1

2

您的代码的问题是内部类正在尝试访问外部类的成员变量。这是不可能的,因为它们都使用self来引用它们当前的实例,并且内部类的self参数隐藏了外部类的self. 您需要为其中一个使用不同的名称。

虽然您实际上可以在其中一个方法中为第一个参数名称使用不同的名称,但我建议self在定义嵌套类之前简单地将附加名称绑定到外部对象:

class Outer(object):
    def __init__(self):
        self.foo = "foo"

    def do_stuff(self):
        outer_self = self # give an extra name to `self` that won't be shadowed

        class Inner(object):
            def __init__(self):
                 self.bar = "bar"

            def do_inner_stuff(self):
                print(outer_self.foo, self.bar) # access the outer class's data

        i = Inner()
        i.do_inner_stuff()

这可行,但它仍然可能不是最好的设计。嵌套类是不可序列化的,调试起来很麻烦,如果可能的话应该避免。

一个更好的想法是取消嵌套类,只需将所需的数据从外部类传递到内部类的构造函数,其中可以将引用保存为成员变量:

class Outer(object):
    def __init__(self):
        self.foo = "foo"

    def do_stuff(self):
        i = Inner(self.foo) # pass relevant data to constructor
        i.do_inner_stuff()

class Inner(object):
    def __init__(self, foo):
        self.foo = foo # keep a reference to passed data
        self.bar = "bar"

    def do_inner_stuff(self):
        print(self.foo, self.bar)  # use the data
于 2013-01-24T02:20:36.530 回答