我有一個非常大的表(目前有5500萬行,可能更多),我需要選擇它的子集並對這些子集,很多次執行非常簡單的操作。看起來像大熊貓可能是在python中做到這一點的最佳方式,但我遇到了優化問題。在多列/多索引上優化大熊貓查詢
我試着創建一個與我的真實數據集非常匹配的假數據集(雖然它大約小5-10倍)。這仍然很大,需要大量內存等等。我正在查詢四列,還有兩列用於計算。
import pandas
import numpy as np
import timeit
n=10000000
mdt = pandas.DataFrame()
mdt['A'] = np.random.choice(range(10000,45000,1000), n)
mdt['B'] = np.random.choice(range(10,400), n)
mdt['C'] = np.random.choice(range(1,150), n)
mdt['D'] = np.random.choice(range(10000,45000), n)
mdt['x'] = np.random.choice(range(400), n)
mdt['y'] = np.random.choice(range(25), n)
test_A = 25000
test_B = 25
test_C = 40
test_D = 35000
eps_A = 5000
eps_B = 5
eps_C = 5
eps_D = 5000
f1 = lambda : mdt.query('@[email protected]_A <= A <= @[email protected]_A & ' +
'@[email protected]_B <= B <= @[email protected]_B & ' +
'@[email protected]_C <= C <= @[email protected]_C & ' +
'@[email protected]_D <= D <= @[email protected]_D')
這個選擇(我的隨機數據集),1848年行:
len(f1())
Out[289]: 1848
它讓每個查詢約0.1-0.15秒:
timeit.timeit(f1,number=10)/10
Out[290]: 0.10734589099884033
所以我想我必須通過排序和索引表可以做得更好,對嗎?我可以利用的事實,這一切都是一個int,所以我可以做切片..
mdt2 = mdt.set_index(['A', 'B', 'C', 'D']).sortlevel()
f2 = lambda : mdt2.loc[(slice(test_A-eps_A, test_A+eps_A),
slice(test_B-eps_B, test_B+eps_B),
slice(test_C-eps_C, test_C+eps_C),
slice(test_D-eps_D, test_D+eps_D)), :]
len(f2())
Out[299]: 1848
它需要很多長:
timeit.timeit(f2,number=10)/10
Out[295]: 7.335134506225586
我在這裏失去了一些東西?看起來我可以像numpy.searchsorted那樣做,但我想不出如何在多列上做到這一點。熊貓是錯誤的選擇嗎?
'DataFrame.query' FTW! –
謝謝,傑夫!這很有幫助,雖然看起來基本答案是「你不能比查詢更好」。看起來很奇怪,沒有辦法利用排序後的數據。 此外,這似乎表明,parens是不需要的(雖然他們當然從未受傷): http://pandas.pydata.org/pandas-docs/stable/indexing.html#query-python-versus -pandas-syntax-comparison – benjamin
文檔不包括鏈式比較'a <= val <= b'' AND多個表達式的情況,它們是必要的。此外,索引器DO利用分類。一般情況下,除非你正在尋找個人價值,但這並沒有太大的區別,因爲你在這裏尋找任意範圍/列表喜歡。根據您實際選擇的內容,您最好使用基於磁盤的行存儲(例如''HDFStore''),但使用YMMV。 – Jeff