web-dev-qa-db-ja.com

パンダのマルチインデックスのメリットは?

それで、MultiIndexなしでDataFrame.groupbyを使用してサブサンプリング/クロスセクションを実行できることを学びました。

一方、DataFrameにMultiIndexがある場合でも、DataFrame.groupbyを使用してサブサンプリング/クロスセクションを実行する必要があります。

では、印刷時の階層の非常に役立つ、かなりの表示とは別に、MultiIndexは何に適していますか?

34
K.-Michael Aye

pandas 0.4リリースで、階層型インデックス(「マルチレベル」インデックスとも呼ばれる)が導入されました。

これは、特により高次元のデータを操作するために、いくつかの非常に高度なデータ分析と操作への扉を開きます。本質的には、たとえば、2次元の表構造(DataFrame)に任意の高次元のデータを効果的に格納および操作することができます。

次のようにMultiIndexを使用してデータフレームを構築することを想像してください:

import pandas as pd
import numpy as np

np.arrays = [['one','one','one','two','two','two'],[1,2,3,1,2,3]]

df = pd.DataFrame(np.random.randn(6,2),index=pd.MultiIndex.from_tuples(list(Zip(*np.arrays))),columns=['A','B'])

df  # This is the dataframe we have generated

          A         B
one 1 -0.732470 -0.313871
    2 -0.031109 -2.068794
    3  1.520652  0.471764
two 1 -0.101713 -1.204458
    2  0.958008 -0.455419
    3 -0.191702 -0.915983

このdfは、単純に2次元のデータ構造です

df.ndim

2

しかし、出力を3次元のデータ構造として見ると想像できます。

  • one1データあり-0.732470 -0.313871
  • one2データあり-0.031109 -2.068794
  • one3データあり1.520652 0.471764

別名:「2次元の表構造で任意の高次元のデータを効果的に格納および操作する」

これは単なる「きれいなディスプレイ」ではありません。これで、階層インデックスが作成されたため、データを簡単に取得できるという利点があります。

例えば。

In [44]: df.ix["one"]
Out[44]: 
          A         B
1 -0.732470 -0.313871
2 -0.031109 -2.068794
3  1.520652  0.471764

「1」に属するデータのグループにのみ新しいデータフレームを提供します。

そして、これを行うことでデータ選択をさらに絞り込むことができます:

In [45]: df.ix["one"].ix[1]
Out[45]: 
A   -0.732470
B   -0.313871
Name: 1

そしてもちろん、特定の値が必要な場合は、例を示します:-

In [46]: df.ix["one"].ix[1]["A"]
Out[46]: -0.73247029752040727

したがって、(上記の例に示されている2つのインデックスに加えて)さらに多くのインデックスがある場合、groupbyを必要とせずに、基本的にドリルダウンして、本当に関心のあるデータセットを選択できます。

データフレームから断面(行または列)を取得することもできます...

行ごと:-

In [47]: df.xs('one')
Out[47]: 
          A         B
1 -0.732470 -0.313871
2 -0.031109 -2.068794
3  1.520652  0.471764

列ごと:-

In [48]: df.xs('B', axis=1)
Out[48]: 
one  1   -0.313871
     2   -2.068794
     3    0.471764
two  1   -1.204458
     2   -0.455419
     3   -0.915983
Name: B
61
Calvin Cheng

@Calvin Chengによる素晴らしい投稿ですが、私もこれを試してみようと思いました。

マルチインデックスを使用する場合:

  1. 1つの列の値だけでは行を一意に識別できない場合。
  2. データが論理的に階層的である場合-複数のディメンションまたは「レベル」があることを意味します。

なぜ(あなたの中心的な質問)-少なくともこれらはIMOの最大の利点です:

  1. Stack()およびunstack()による簡単な操作
  2. 複数の列レベルがある場合の簡単な計算
  3. スライス/フィルタリング用の構文糖

例:

_                                                       Dollars  Units
Date       Store   Category Subcategory UPC EAN
2018-07-10 Store 1 Alcohol  Liqour      80480280024    154.77      7
           Store 2 Alcohol  Liqour      80480280024     82.08      4
           Store 3 Alcohol  Liqour      80480280024    259.38      9
           Store 1 Alcohol  Liquor      80432400630    477.68     14
                                        674545000001   139.68      4
           Store 2 Alcohol  Liquor      80432400630    203.88      6
                                        674545000001   377.13     13
           Store 3 Alcohol  Liquor      80432400630    239.19      7
                                        674545000001   432.32     14
           Store 1 Beer     Ales        94922755711     65.17      7
                                        702770082018   174.44     14
                                        736920111112    50.70      5
           Store 2 Beer     Ales        94922755711    129.60     12
                                        702770082018   107.40     10
                                        736920111112    59.65      5
           Store 3 Beer     Ales        94922755711    154.00     14
                                        702770082018   137.40     10
                                        736920111112   107.88     12
           Store 1 Beer     Lagers      702770081011   156.24     12
           Store 2 Beer     Lagers      702770081011   137.06     11
           Store 3 Beer     Lagers      702770081011   119.52      8    
_

1)店舗間の売上高を簡単に比較したい場合は、df.unstack('Store')を使用してすべてを並べて並べることができます。

_                                             Dollars                   Units
Store                                        Store 1 Store 2 Store 3 Store 1 Store 2 Store 3
Date       Category Subcategory UPC EAN
2018-07-10 Alcohol  Liqour      80480280024   154.77   82.08  259.38       7       4       9
                    Liquor      80432400630   477.68  203.88  239.19      14       6       7
                                674545000001  139.68  377.13  432.32       4      13      14
           Beer     Ales        94922755711    65.17  129.60  154.00       7      12      14
                                702770082018  174.44  107.40  137.40      14      10      10
                                736920111112   50.70   59.65  107.88       5       5      12
                    Lagers      702770081011  156.24  137.06  119.52      12      11       8
_

2)複数の列で簡単に計算することもできます。たとえば、_df['Dollars'] / df['Units']_は、複数の操作を行わないすべてのストアについて、各ストアのドルをその単位で割ります。

_Store                                         Store 1  Store 2  Store 3
Date       Category Subcategory UPC EAN
2018-07-10 Alcohol  Liqour      80480280024     22.11    20.52    28.82
                    Liquor      80432400630     34.12    33.98    34.17
                                674545000001    34.92    29.01    30.88
           Beer     Ales        94922755711      9.31    10.80    11.00
                                702770082018    12.46    10.74    13.74
                                736920111112    10.14    11.93     8.99
                    Lagers      702770081011    13.02    12.46    14.94
_

3)次に、特定の行のみにフィルタリングする場合は、

_df[(df[col1] == val1) and (df[col2] == val2) and (df[col3] == val3)]
_

形式、代わりに.xsまたは.queryを使用できます(これらは通常のdfで機能しますが、あまり役に立ちません)。構文は代わりに次のようになります。

_df.xs((val1, val2, val3), level=(col1, col2, col3))
_

より多くの例がこれにあります チュートリアルノート まとめました。

9
ZaxR