Python 动态生成视图
我有几个类都引用相同的数据帧,但数据帧中只有一部分与每个类相关。我还希望在不使用高级索引的情况下轻松访问相关行,因为由于索引中的数字if级别,它变得重复。因此,我编写了生成分部函数的代码,以便每个类都可以查看其切片Python 动态生成视图,python,pandas,functools,Python,Pandas,Functools,我有几个类都引用相同的数据帧,但数据帧中只有一部分与每个类相关。我还希望在不使用高级索引的情况下轻松访问相关行,因为由于索引中的数字if级别,它变得重复。因此,我编写了生成分部函数的代码,以便每个类都可以查看其切片 from functools import partial import pandas as pd import numpy as np import dateutil.relativedelta as rd import datetime as dt class baz(obje
from functools import partial
import pandas as pd
import numpy as np
import dateutil.relativedelta as rd
import datetime as dt
class baz(object):
pass
groups = ['foo', 'foo', 'bar', 'bar']
items = ['x','y', 'x', 'y']
diff = rd.relativedelta(years=1)
dates = [dt.date(2013,1,1) + (diff * shift) for shift in xrange(4)] * 2
index = pd.MultiIndex.from_arrays([groups, items], names=['groups', 'items'])
values = np.random.randn(4,8)
data = pd.DataFrame(values, index=index, columns=dates)
def view_data(group, item):
return data.ix[group, item]
foo = baz()
bar = baz()
# I use partial because I want lazy evaluation
foo.x = partial(view_data, 'foo', 'x')
foo.y = partial(view_data, 'foo', 'y')
bar.x = partial(view_data, 'bar', 'x')
bar.y = partial(view_data, 'bar', 'y')
foo.x()
但是,我更希望引用不必看起来像foo.x()[date],而可以看起来像foo.x[date]
因此,我创建了一个decorator来包装函数并返回值
def execute_func(func):
def inner(*args, **kwargs):
return func(*args, **kwargs)
return inner()
foo.x = execute_func(partial(view_data, 'foo', 'x'))
foo.y = execute_func(partial(view_data, 'foo', 'y'))
bar.x = execute_func(partial(view_data, 'bar', 'x'))
bar.y = execute_func(partial(view_data, 'bar', 'y'))
我担心的是,我不会总是获得数据帧的当前状态
这是实现我的目标的正确方法吗?我个人建议您将数据帧包装在如下对象中:
class MyDataFrameView(object):
def __init__(self, df):
self.data = df
def x(self):
return self.data.ix['foo', 'x']
def y(self):
return self.data.ix['bar', 'y']
df = MyDataFrameView(data)
df.x()
你这样使用它:
class MyDataFrameView(object):
def __init__(self, df):
self.data = df
def x(self):
return self.data.ix['foo', 'x']
def y(self):
return self.data.ix['bar', 'y']
df = MyDataFrameView(data)
df.x()
如果更直观的话,您可以进一步添加方法作为属性
@property
def y(self):
return self.data.ix['bar', 'y']
它本质上做的事情和你现在做的一样,但是它更简单,面向对象编程,而且——至少在我看来——更容易理解
您始终可以访问数据帧,如下所示:
df.data
或者,您可以直接在视图对象上实现更多方法,例如:
@property
def ix(self):
return self.data.ix
def __getitem__(self, key):
return self.data.__getitem__(key)
因此,对象的行为更像一个数据帧
请注意,这并不是真正的“动态”。如果您想要一种真正的动态方式,也可以使用getattr方法来实现
def __getattr__(self, attr):
#code that "routes" to do the right thing given attr
这种模式通常称为组合,我最喜欢的实现“问题”的方法是使用
@property def x():…;将x作为属性添加到所有数据帧中。。。;pd.DataFrame.x=x
,直接子类化DataFrame也是一个选项。。。