10

優れたpandasパッケージを使用して、さまざまな気象診断データを大量に処理していますが、データをつなぎ合わせると、すぐにディメンションが不足します。ドキュメントを見ると、を使用するMultiIndexと問題が解決する可能性がありますが、それを自分の状況に適用する方法がわかりません-ドキュメントには、ランダムなデータとDataFramesを使用してマルチインデックスを作成する例が示されていますが、既存のシリーズは示されていません時系列データ。

バックグラウンド

私が使用している基本的なデータ構造には、2つの主要なフィールドが含まれています。

  • metadata、これは、数値が何であるかを説明するキーと値のペアで構成される辞書です。
  • data、これは番号自体を含むパンダのデータ構造です。

最小公分母は時系列データであるため、基本構造にはパンダSeriesオブジェクトがdataエントリとして含まれ、metadataフィールドにはそれらの数値が実際に何であるかが示されます(たとえば、東太平洋上の10メートルの風のベクトルRMSエラー、24時間の予測実験テスト1)。

私は、その最小公分母を採用し、さまざまな時系列を結合して、結果をより有用にし、簡単な組み合わせを可能にすることを検討しています。たとえば、すべての異なるリードタイムを確認したい場合があります-リードタイム(実験、地域など)を除いて同じメタデータエントリを共有する時系列を取得し、新しいオブジェクトを返すフィルタールーチンがあります。フィールドはmetadata一般的なエントリのみで構成され(つまりLead Time、削除されています)、フィールドは値で指定された列ラベルをdata持つパンダになります。これをもう一度拡張して、結果のフレームを取得し、パンダを与えるために変化する別のエントリ(たとえば)と一緒にグループ化することができますDataFrameLead TimeExperimentPanel。アイテムインデックスがExperiment構成フレームからのメタデータ値によって与えられ、オブジェクトの新しいメタデータにLead Timeまたはが含まれていないエントリの場合Experiment

これらの複合オブジェクトを反復処理するiterseriesと、フレームのiterframesルーチンとパネルのルーチンがあり、1つのディメンションを削除するときに、適切なメタデータ/データのペアを再構築します(つまり、列全体でリードタイムが変化するフレームからのシリーズにはすべてが含まれます親のメタデータとLead Time列ラベルから取得した値で復元されたフィールド)。これはうまくいきます。

問題

dropnaディメンションが不足し(Panelで最大3D)、Panelですべてが整列された後、空の列を削除するなどの方法も使用できません(これにより、要約統計量をプロットするときにいくつかのバグが発生しました)。より高次元のデータでパンダを使用することについて読むことは、MultiIndexとその使用について読むことにつながりました。ドキュメントに記載されている例を試しましたが、それを自分の状況に適用する方法がまだ少しわかりません。どんな方向でも役に立ちます。次のことができるようになりたい:

  • 私のSeriesベースのデータを任意の数の次元に沿ってマルチインデックスに結合しますDataFrame(これは素晴らしいことです-シリーズからフレームを作成するための1つの呼び出しを排除し、次にフレームからパネルを作成するための別の呼び出しを排除します)
  • 結果のマルチインデックスを繰り返しDataFrame、単一のディメンションを削除して、コンポーネントのメタデータをリセットできるようにします。

編集-コードサンプルを追加

以下のWesMcKinneyの答えは、ほぼ正確に私が必要としているものです。問題は、要素のグループ化を開始した後、操作する必要のあるシリーズベースのストレージオブジェクトからDataFrameベースのオブジェクトへの最初の変換にあります。Data-Frame-backedクラスには、シリーズベースのオブジェクトのリストと列間で変化するメタデータフィールドを取り込む次のメソッドがあります。

@classmethod
def from_list(cls, results_list, column_key):
    """
    Populate object from a list of results that all share the metadata except
    for the field `column_key`.

    """
    # Need two copies of the input results - one for building the object
    # data and one for building the object metadata
    for_data, for_metadata = itertools.tee(results_list)

    self             = cls()
    self.column_key  = column_key
    self.metadata    = next(for_metadata).metadata.copy()
    if column_key in self.metadata:
        del self.metadata[column_key]
    self.data = pandas.DataFrame(dict(((transform(r[column_key]), r.data)
                                        for r in for_data)))
    return self

このルーチンで指定されたフレームを取得したら、以下に示すさまざまな操作を簡単に適用できます。特定のユーティリティは、names呼び出し時にフィールドを使用できます。concatこれにより、列キーの名前が保存されるため、内部に保存する必要がなくなります。そのインデックスディメンションの名前としてMultiIndexにあります。

以下のソリューションを実装して、一致するシリーズベースのクラスのリストとキーのリストを取得し、グループ化を順番に実行できるようにしたいと思います。ただし、列が何を表すかは事前にわかりません。そのため、次のようにします。

  • シリーズデータを1-DDataFrameに保存することは私には本当に意味がありません
  • 最初のシリーズ->フレームグループ化からインデックスと列の名前を設定する方法がわかりません
4

1 に答える 1

10

Series DataFrameを結合して、列にMultiIndexを作成するためにpandas.concat、引数とともに使用することをお勧めします。keys

In [20]: data
Out[20]: 
{'a': 2012-04-16    0
2012-04-17    1
2012-04-18    2
2012-04-19    3
2012-04-20    4
2012-04-21    5
2012-04-22    6
2012-04-23    7
2012-04-24    8
2012-04-25    9
Freq: D,
 'b': 2012-04-16    0
2012-04-17    1
2012-04-18    2
2012-04-19    3
2012-04-20    4
2012-04-21    5
2012-04-22    6
2012-04-23    7
2012-04-24    8
2012-04-25    9
Freq: D,
 'c': 2012-04-16    0
2012-04-17    1
2012-04-18    2
2012-04-19    3
2012-04-20    4
2012-04-21    5
2012-04-22    6
2012-04-23    7
2012-04-24    8
2012-04-25    9
Freq: D}

In [21]: df = pd.concat(data, axis=1, keys=['a', 'b', 'c'])

In [22]: df
Out[22]: 
            a  b  c
2012-04-16  0  0  0
2012-04-17  1  1  1
2012-04-18  2  2  2
2012-04-19  3  3  3
2012-04-20  4  4  4
2012-04-21  5  5  5
2012-04-22  6  6  6
2012-04-23  7  7  7
2012-04-24  8  8  8
2012-04-25  9  9  9

In [23]: df2 = pd.concat([df, df], axis=1, keys=['group1', 'group2'])

In [24]: df2
Out[24]: 
            group1        group2      
                 a  b  c       a  b  c
2012-04-16       0  0  0       0  0  0
2012-04-17       1  1  1       1  1  1
2012-04-18       2  2  2       2  2  2
2012-04-19       3  3  3       3  3  3
2012-04-20       4  4  4       4  4  4
2012-04-21       5  5  5       5  5  5
2012-04-22       6  6  6       6  6  6
2012-04-23       7  7  7       7  7  7
2012-04-24       8  8  8       8  8  8
2012-04-25       9  9  9       9  9  9

次に、次のようになります。

In [25]: df2['group2']
Out[25]: 
            a  b  c
2012-04-16  0  0  0
2012-04-17  1  1  1
2012-04-18  2  2  2
2012-04-19  3  3  3
2012-04-20  4  4  4
2012-04-21  5  5  5
2012-04-22  6  6  6
2012-04-23  7  7  7
2012-04-24  8  8  8
2012-04-25  9  9  9

あるいは

In [27]: df2.xs('b', axis=1, level=1)
Out[27]: 
            group1  group2
2012-04-16       0       0
2012-04-17       1       1
2012-04-18       2       2
2012-04-19       3       3
2012-04-20       4       4
2012-04-21       5       5
2012-04-22       6       6
2012-04-23       7       7
2012-04-24       8       8
2012-04-25       9       9

あなたは任意に多くのレベルを持つことができます:

In [29]: pd.concat([df2, df2], axis=1, keys=['tier1', 'tier2'])
Out[29]: 
             tier1                       tier2                    
            group1        group2        group1        group2      
                 a  b  c       a  b  c       a  b  c       a  b  c
2012-04-16       0  0  0       0  0  0       0  0  0       0  0  0
2012-04-17       1  1  1       1  1  1       1  1  1       1  1  1
2012-04-18       2  2  2       2  2  2       2  2  2       2  2  2
2012-04-19       3  3  3       3  3  3       3  3  3       3  3  3
2012-04-20       4  4  4       4  4  4       4  4  4       4  4  4
2012-04-21       5  5  5       5  5  5       5  5  5       5  5  5
2012-04-22       6  6  6       6  6  6       6  6  6       6  6  6
2012-04-23       7  7  7       7  7  7       7  7  7       7  7  7
2012-04-24       8  8  8       8  8  8       8  8  8       8  8  8
2012-04-25       9  9  9       9  9  9       9  9  9       9  9  9
于 2012-06-14T17:11:45.560 に答える