38

そのため、サブサンプリング/断面を行うためのMultiIndexがなくてもDataFrame.groupbyを使用できることを学びました。

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

では、印刷時に階層が非常に便利できれいに表示されることを除けば、MultiIndexは何に適しているのでしょうか。

4

3 に答える 3

68

階層インデックス(「マルチレベル」インデックスとも呼ばれます)は、pandas0.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
于 2012-11-05T05:22:05.390 に答える
14

@Calvin Chengによる素晴らしい投稿ですが、私もこれを突き刺すと思いました。

MultiIndexを使用する場合:

  1. 単一の列の値では、行を一意に識別するのに十分でない場合。
  2. データが論理的に階層的である場合-つまり、データには複数のディメンションまたは「レベル」があります。</ li>

なぜ(あなたの中心的な質問)-少なくともこれらは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を使用できます(はい、これらは通常のdfsで機能しますが、あまり役に立ちません)。代わりに、構文は次のようになります。

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

私がまとめたこのチュートリアルノートブックには、さらに多くの例があります。

于 2018-08-09T21:13:42.000 に答える
2

マルチインデックスを使用する代わりに、データフレームの複数の列を使用してデータを保存することもできます。マルチインデックスは、ナイーブな列ストレージよりもパフォーマンスが向上すると予想されますが、Pandas v 1.1.4の時点では、そうではないようです。

ティミニグ

import numpy as np
import pandas as pd

np.random.seed(2020)
inv = pd.DataFrame({
    'store_id': np.random.choice(10000, size=10**7),
    'product_id': np.random.choice(1000, size=10**7),
    'stock': np.random.choice(100, size=10**7),
})
# Create a DataFrame with a multiindex
inv_multi = inv.groupby(['store_id', 'product_id'])[['stock']].agg('sum')
print(inv_multi)
                     stock
store_id product_id       
0        2              48
         4              18
         5              58
         7             149
         8             158
...                    ...
9999     992           132
         995           121
         996           105
         998            99
         999            16

[6321869 rows x 1 columns]
# Create a DataFrame without a multiindex
inv_cols = inv_multi.reset_index()
print(inv_cols)
         store_id  product_id  stock
0               0           2     48
1               0           4     18
2               0           5     58
3               0           7    149
4               0           8    158
...           ...         ...    ...
6321864      9999         992    132
6321865      9999         995    121
6321866      9999         996    105
6321867      9999         998     99
6321868      9999         999     16

[6321869 rows x 3 columns]
%%timeit
inv_multi.xs(key=100, level='store_id')
10 loops, best of 3: 20.2 ms per loop

%%timeit
inv_cols.loc[inv_cols.store_id == 100]
The slowest run took 8.79 times longer than the fastest. This could mean that an intermediate result is being cached.
100 loops, best of 3: 11.5 ms per loop

%%timeit
inv_multi.xs(key=100, level='product_id')
100 loops, best of 3: 9.08 ms per loop

%%timeit
inv_cols.loc[inv_cols.product_id == 100]
100 loops, best of 3: 12.2 ms per loop

%%timeit
inv_multi.xs(key=(100, 100), level=('store_id', 'product_id'))
10 loops, best of 3: 29.8 ms per loop

%%timeit
inv_cols.loc[(inv_cols.store_id == 100) & (inv_cols.product_id == 100)]
10 loops, best of 3: 28.8 ms per loop

結論

MultiIndexを使用する利点は、構文糖衣、自己文書化データ、およびunstack()@ZaxRの回答で述べたような関数の小さな便利さです。パフォーマンスはメリットではなく、チャンスを逃したようです。

于 2020-11-23T17:18:33.687 に答える