Tôi có một bảng rất lớn (hiện tại là 55 triệu hàng, có thể nhiều hơn) và tôi cần chọn tập con của nó và thực hiện các thao tác rất đơn giản trên các tập con đó, rất nhiều lần . Dường như gấu trúc có thể là cách tốt nhất để làm điều này trong python, nhưng tôi đang chạy vào các vấn đề tối ưu hóa.tối ưu hóa truy vấn gấu trúc trên nhiều cột/multiindex
Tôi đã cố tạo một tập dữ liệu giả phù hợp chặt chẽ với tập dữ liệu thực của tôi (mặc dù nó nhỏ hơn ~ 5-10 lần). Điều này vẫn còn lớn, mất rất nhiều bộ nhớ, vv Có bốn cột mà tôi đang truy vấn và hai cột mà tôi đang sử dụng để tính toán.
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')
Lựa chọn này (đối với dữ liệu ngẫu nhiên của tôi) 1848 hàng:
len(f1())
Out[289]: 1848
Và nó mất khoảng 0,1-0,15 giây cho mỗi truy vấn:
timeit.timeit(f1,number=10)/10
Out[290]: 0.10734589099884033
Vì vậy, tôi nghĩ rằng tôi phải có thể làm tốt hơn bằng cách sắp xếp và lập chỉ mục bảng, đúng không? Và tôi có thể tận dụng thực tế là tất cả mọi thứ là một int, vì vậy tôi có thể làm lát ..
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
và phải mất rất nhiều còn:
timeit.timeit(f2,number=10)/10
Out[295]: 7.335134506225586
Am tôi thiếu cái gì ở đây? Nó có vẻ như tôi có thể làm một cái gì đó như numpy.searchsorted, nhưng tôi không thể nghĩ làm thế nào để làm điều đó trên nhiều cột. Gấu trúc là sự lựa chọn sai?
'DataFrame.query' FTW! –
Cảm ơn, Jeff! Điều này là hữu ích, mặc dù nó có vẻ như câu trả lời cơ bản là "bạn không thể làm tốt hơn so với truy vấn". Nó có vẻ lạ rằng không có một cách để tận dụng lợi thế của dữ liệu được sắp xếp. Ngoài ra, điều này dường như chỉ ra rằng các parens là không cần thiết (mặc dù tất nhiên họ không bao giờ làm tổn thương): http://pandas.pydata.org/pandas-docs/stable/indexing.html#query-python-versus -pandas-syntax-comparison – benjamin
Các tài liệu không bao gồm trường hợp so sánh chuỗi '' a <= val <= b'' AND nhiều biểu thức, khi chúng cần thiết. Hơn nữa, chỉ số DO tận dụng lợi thế của việc sắp xếp. Nói chung, trừ khi bạn đang tìm kiếm các giá trị riêng lẻ, điều này không tạo ra nhiều khác biệt, vì bạn đang tìm kiếm các phạm vi tùy ý/danh sách thích ở đây. Tùy thuộc vào những gì bạn đang thực sự chọn, bạn có thể nên sử dụng cửa hàng hàng dựa trên đĩa (ví dụ: '' HDFStore''), nhưng YMMV. – Jeff