33

パンダを使用したOHLCデータの時間枠変換に関して、誰かが私を正しい方向に向けてくれませんか?私がやろうとしているのは、より短い時間枠のデータを前提として、より高い時間枠のデータでデータフレームを構築することです。

たとえば、次の1分(M1)データがあるとします。

                       Open    High     Low   Close  Volume
Date                                                       
1999-01-04 10:22:00  1.1801  1.1819  1.1801  1.1817       4
1999-01-04 10:23:00  1.1817  1.1818  1.1804  1.1814      18
1999-01-04 10:24:00  1.1817  1.1817  1.1802  1.1806      12
1999-01-04 10:25:00  1.1807  1.1815  1.1795  1.1808      26
1999-01-04 10:26:00  1.1803  1.1806  1.1790  1.1806       4
1999-01-04 10:27:00  1.1801  1.1801  1.1779  1.1786      23
1999-01-04 10:28:00  1.1795  1.1801  1.1776  1.1788      28
1999-01-04 10:29:00  1.1793  1.1795  1.1782  1.1789      10
1999-01-04 10:31:00  1.1780  1.1792  1.1776  1.1792      12
1999-01-04 10:32:00  1.1788  1.1792  1.1788  1.1791       4

毎分オープン、ハイ、ロー、クローズ(OHLC)とボリュームの値があり、次のような5分間の読み取り値(M5)のセットを作成したいと思います。

                       Open    High     Low   Close  Volume
Date                                                       
1999-01-04 10:25:00  1.1807  1.1815  1.1776  1.1789      91
1999-01-04 10:30:00  1.1780  1.1792  1.1776  1.1791      16

したがって、ワークフローは次のとおりです。

  • Openは、タイムウィンドウの最初の行のOpenです。
  • 高は時間枠の中で最も高い高です
  • 低は最低です低
  • クローズは最後のクローズです
  • ボリュームは単にボリュームの合計です

ただし、いくつかの問題があります。

  • データにギャップがあります(10:30:00の行がないことに注意してください)
  • 5分間隔はラウンドタイムで開始する必要があります。たとえば、M5は10:22:00ではなく10:25:00に開始します。
  • まず、この例のように不完全なセットを省略したり、含めたりすることができます(したがって、10:20:00の5分間のエントリを持つことができます)

アップダウンサンプリングに関するPandasのドキュメントに例が示されていますが、アップサンプリングされた行の値として平均値が使用されているため、ここでは機能しません。私は使ってみgroupbyましaggたが、役に立ちませんでした。最高の高値と最低の低値を取得するのはそれほど難しいことではないかもしれませんが、最初に開いて最後に閉じる方法がわかりません。

私が試したのは、次のようなものです。

grouped = slice.groupby( dr5minute.asof ).agg( 
    { 'Low': lambda x : x.min()[ 'Low' ], 'High': lambda x : x.max()[ 'High' ] } 
)

しかし、それは私が理解していない次のエラーになります:

In [27]: grouped = slice.groupby( dr5minute.asof ).agg( { 'Low' : lambda x : x.min()[ 'Low' ], 'High' : lambda x : x.max()[ 'High' ] } )
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
/work/python/fxcruncher/<ipython-input-27-df50f9522a2f> in <module>()
----> 1 grouped = slice.groupby( dr5minute.asof ).agg( { 'Low' : lambda x : x.min()[ 'Low' ], 'High' : lambda x : x.max()[ 'High' ] } )

/usr/lib/python2.7/site-packages/pandas/core/groupby.pyc in agg(self, func, *args, **kwargs)
    242         See docstring for aggregate
    243         """
--> 244         return self.aggregate(func, *args, **kwargs)
    245 
    246     def _iterate_slices(self):

/usr/lib/python2.7/site-packages/pandas/core/groupby.pyc in aggregate(self, arg, *args, **kwargs)
   1153                     colg = SeriesGroupBy(obj[col], column=col,
   1154                                          grouper=self.grouper)
-> 1155                     result[col] = colg.aggregate(func)
   1156 
   1157             result = DataFrame(result)

/usr/lib/python2.7/site-packages/pandas/core/groupby.pyc in aggregate(self, func_or_funcs, *args, **kwargs)
    906                 return self._python_agg_general(func_or_funcs, *args, **kwargs)
    907             except Exception:
--> 908                 result = self._aggregate_named(func_or_funcs, *args, **kwargs)
    909 
    910             index = Index(sorted(result), name=self.grouper.names[0])

/usr/lib/python2.7/site-packages/pandas/core/groupby.pyc in _aggregate_named(self, func, *args, **kwargs)
    976             grp = self.get_group(name)
    977             grp.name = name
--> 978             output = func(grp, *args, **kwargs)
    979             if isinstance(output, np.ndarray):
    980                 raise Exception('Must produce aggregated value')

/work/python/fxcruncher/<ipython-input-27-df50f9522a2f> in <lambda>(x)
----> 1 grouped = slice.groupby( dr5minute.asof ).agg( { 'Low' : lambda x : x.min()[ 'Low' ], 'High' : lambda x : x.max()[ 'High' ] } )

IndexError: invalid index to scalar variable.

ですから、それを行う上での助けをいただければ幸いです。選択したパスが機能しない場合は、他の比較的効率的なアプローチを提案してください(数百万行あります)。金融処理にパンダを使用するためのいくつかのリソースもいいでしょう。

4

4 に答える 4

16

あなたのアプローチは健全ですが、agg() に適用される dict-of functions の各関数が、キー値に一致する列を反映した Series オブジェクトを受け取るため、失敗します。したがって、列ラベルを再度フィルター処理する必要はありません。これにより、groupby が順序を維持すると仮定すると、Series をスライスして、Open/Close 列の最初/最後の要素を抽出できます (注: groupby のドキュメントでは、元のデータ シリーズの順序を維持するとは主張していませんが、実際にはそうなっているようです)。

In [50]: df.groupby(dr5minute.asof).agg({'Low': lambda s: s.min(), 
                                         'High': lambda s: s.max(),
                                         'Open': lambda s: s[0],
                                         'Close': lambda s: s[-1],
                                         'Volume': lambda s: s.sum()})
Out[50]: 
                      Close    High     Low    Open  Volume
key_0                                                      
1999-01-04 10:20:00  1.1806  1.1819  1.1801  1.1801      34
1999-01-04 10:25:00  1.1789  1.1815  1.1776  1.1807      91
1999-01-04 10:30:00  1.1791  1.1792  1.1776  1.1780      16

参考までに、次の表に、groupby オブジェクト タイプに基づく集約関数の予想される入力および出力タイプと、集約関数が agg() にどのように渡されるかをまとめたものを示します。

                  agg() method     agg func    agg func          agg()
                  input type       accepts     returns           result
GroupBy Object
SeriesGroupBy     function         Series      value             Series
                  dict-of-funcs    Series      value             DataFrame, columns match dict keys
                  list-of-funcs    Series      value             DataFrame, columns match func names
DataFrameGroupBy  function         DataFrame   Series/dict/ary   DataFrame, columns match original DataFrame
                  dict-of-funcs    Series      value             DataFrame, columns match dict keys, where dict keys must be columns in original DataFrame
                  list-of-funcs    Series      value             DataFrame, MultiIndex columns (original cols x func names)

上記の表から、集約が複数の列へのアクセスを必要とする場合、唯一のオプションは、単一の関数を DataFrameGroupBy オブジェクトに渡すことです。したがって、元のタスクを達成する別の方法は、次のような関数を定義することです。

def ohlcsum(df):
    df = df.sort()
    return {
       'Open': df['Open'][0],
       'High': df['High'].max(),
       'Low': df['Low'].min(),
       'Close': df['Close'][-1],
       'Volume': df['Volume'].sum()
      }

agg() を適用します。

In [30]: df.groupby(dr5minute.asof).agg(ohlcsum)
Out[30]: 
                       Open    High     Low   Close  Volume
key_0                                                      
1999-01-04 10:20:00  1.1801  1.1819  1.1801  1.1806      34
1999-01-04 10:25:00  1.1807  1.1815  1.1776  1.1789      91
1999-01-04 10:30:00  1.1780  1.1792  1.1776  1.1791      16

パンダは将来、よりクリーンなビルトイン マジックを提供する可能性がありますが、これで現在の agg() 機能を使用する方法が説明されることを願っています。

于 2012-04-01T20:42:23.170 に答える