2

すべてが同じ pandas データフレームを参照するいくつかのクラスがありますが、各クラスに関連するのはデータ フレームの一部のみです。また、高度なインデックス作成を使用せずに、関連する行に簡単にアクセスできるようにしたいと考えています。これは、インデックス内のレベルが数によって繰り返されるためです。その結果、各クラスがそのスライスを表示できるように、部分関数を生成するコードを作成しました。

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] のように見えることが望ましいと思います。

その結果、関数をラップして値を返すデコレーターを作成しました。

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'))

私の懸念は、データフレームの現在の状態を常に取得できるとは限らないことです。

これは私の目標を達成するための正しい方法ですか?

4

1 に答える 1

3

個人的には、次のように DataFrame をオブジェクトにラップすることをお勧めします。

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

または、 View オブジェクトに直接 pandas メソッドをさらに実装できます。次に例を示します。

@property
def ix(self):
    return self.data.ix

def __getitem__(self, key):
    return self.data.__getitem__(key)

そのため、オブジェクトは DataFrame のように動作します。

実際には「動的」ではないことに注意してください。本当に動的な方法が必要な場合は、getattrメソッドを使用してそれを実装することもできます

def __getattr__(self, attr):
   #code that "routes" to do the right thing given attr

このパターンは一般に構成と呼ばれ、「問題」を実装する私のお気に入りの方法です

于 2014-04-13T14:42:35.410 に答える