コード例:
In [171]: A = np.array([1.1, 1.1, 3.3, 3.3, 5.5, 6.6])
In [172]: B = np.array([111, 222, 222, 333, 333, 777])
In [173]: C = randint(10, 99, 6)
In [174]: df = pd.DataFrame(Zip(A, B, C), columns=['A', 'B', 'C'])
In [175]: df.set_index(['A', 'B'], inplace=True)
In [176]: df
Out[176]:
C
A B
1.1 111 20
222 31
3.3 222 24
333 65
5.5 333 22
6.6 777 74
ここで、A値を取得します。
Q1:範囲[3.3、6.6]-期待される戻り値:[3.3、5.5、6.6]または[3.3、3.3、5.5、6.6]最後の場合、および[ 3.3、5.5]または[3.3、3.3、5.5]でなければ。
Q2:範囲[2.0、4.0]-期待される戻り値:[3.3]または[3.3、3.3]
他のMultiIndexディメンション、たとえばB値についても同じです:
Q:範囲内のデータ行の数として繰り返し[111、500]で-期待される戻り値:[111、222、222、333、333]
より正式な:
Tが列A、B、およびCを持つテーブルであると仮定します。テーブルにはn行が含まれます。テーブルのセルは数値です。たとえば、A double、B、C整数です。テーブルTのDataFrameを作成しましょう。DFと名付けましょう。 DFの列AとBのインデックスを設定してみましょう(重複なし、つまりインデックスとして別々の列AとBはなく、データとして分離)、つまりこの場合はAとBMultiIndex。
質問:
インデックスではない列の場合の上記の質問に対する答えを知っていますが、インデックスの場合は、Webでの長い調査とpandas、成功しませんでした。私が今見ている唯一の方法(追加のプログラミングなし)は、インデックスに加えてデータ列としてAとBの複製を持つことです。
dfをMultiIndex値でクエリするには、たとえば(A> 1.7)and(B <666):
In [536]: result_df = df.loc[(df.index.get_level_values('A') > 1.7) & (df.index.get_level_values('B') < 666)]
In [537]: result_df
Out[537]:
C
A B
3.3 222 43
333 59
5.5 333 56
したがって、たとえば'A'インデックス値を取得するには、まだ必要な場合:
In [538]: result_df.index.get_level_values('A')
Out[538]: Index([3.3, 3.3, 5.5], dtype=object)
問題は、大きなデータフレームでは、インデックスによる選択のパフォーマンスが、ソートされた通常の行の選択よりも10%悪いことです。そして、反復作業、ループ、遅延が累積しました。例を参照してください:
In [558]: df = store.select(STORE_EXTENT_BURSTS_DF_KEY)
In [559]: len(df)
Out[559]: 12857
In [560]: df.sort(inplace=True)
In [561]: df_without_index = df.reset_index()
In [562]: %timeit df.loc[(df.index.get_level_values('END_TIME') > 358200) & (df.index.get_level_values('START_TIME') < 361680)]
1000 loops, best of 3: 562 µs per loop
In [563]: %timeit df_without_index[(df_without_index.END_TIME > 358200) & (df_without_index.START_TIME < 361680)]
1000 loops, best of 3: 507 µs per loop
読みやすくするために、単純に query()
メソッド を使用して、長いdf.index.get_level_values()
を避けます。およびreset_index
/set_index
前後。
ターゲットDataFrame
は次のとおりです。
In [12]: df
Out[12]:
C
A B
1.1 111 68
222 40
3.3 222 20
333 11
5.5 333 80
6.6 777 51
Q1(A
範囲[3.3, 6.6]
)に対する回答:
In [13]: df.query('3.3 <= A <= 6.6') # for closed interval
Out[13]:
C
A B
3.3 222 20
333 11
5.5 333 80
6.6 777 51
In [14]: df.query('3.3 < A < 6.6') # for open interval
Out[14]:
C
A B
5.5 333 80
そしてもちろん、あらゆる種類のインクルードに対して<, <=, >, >=
をいじることができます。
同様に、Q2(A
範囲[2.0, 4.0]
)に対する回答:
In [15]: df.query('2.0 <= A <= 4.0')
Out[15]:
C
A B
3.3 222 20
333 11
Q3(B
範囲内[111, 500]
)に対する回答:
In [16]: df.query('111 <= B <= 500')
Out[16]:
C
A B
1.1 111 68
222 40
3.3 222 20
333 11
5.5 333 80
さらに、col A
とB
のクエリを非常に自然に結合できます!
In [17]: df.query('0 < A < 4 and 150 < B < 400')
Out[17]:
C
A B
1.1 222 40
3.3 222 20
333 11
インデックスのような「フロート」では、直接インデックス作成アクションではなく、常に列として使用する必要があります。これらはすべて、エンドポイントが存在するかどうかにかかわらず機能します。
In [11]: df
Out[11]:
C
A B
1.1 111 81
222 45
3.3 222 98
333 13
5.5 333 89
6.6 777 98
In [12]: x = df.reset_index()
Q1
In [13]: x.loc[(x.A>=3.3)&(x.A<=6.6)]
Out[13]:
A B C
2 3.3 222 98
3 3.3 333 13
4 5.5 333 89
5 6.6 777 98
Q2
In [14]: x.loc[(x.A>=2.0)&(x.A<=4.0)]
Out[14]:
A B C
2 3.3 222 98
3 3.3 333 13
Q3
In [15]: x.loc[(x.B>=111.0)&(x.B<=500.0)]
Out[15]:
A B C
0 1.1 111 81
1 1.1 222 45
2 3.3 222 98
3 3.3 333 13
4 5.5 333 89
インデックスを元に戻したい場合は、単に設定してください。これは安価な操作です。
In [16]: x.loc[(x.B>=111.0)&(x.B<=500.0)].set_index(['A','B'])
Out[16]:
C
A B
1.1 111 81
222 45
3.3 222 98
333 13
5.5 333 89
本当に実際のインデックス値が必要な場合
In [5]: x.loc[(x.B>=111.0)&(x.B<=500.0)].set_index(['A','B']).index
Out[5]:
MultiIndex
[(1.1, 111), (1.1, 222), (3.3, 222), (3.3, 333), (5.5, 333)]