#python #performance #memory #parquet
#python #Производительность #память #паркет
Вопрос:
У меня есть файлы parquet, содержащие миллионы / миллиарды строк, я пытаюсь найти более быстрый процесс применения функции и запроса значений в этих больших таблицах. Пример кода ipynb таблицы из 1 МЛН строк:
from pyarrow import parquet as pq
from ttictoc import TicToc #Preferred time tracker
t = TicToc()
#Function to be applied
def val_calc(x,n_cols):
import random
import string
#Mapping process
abc_vals = string.ascii_uppercase[:n_cols] #N-alphabets in the df
x_map = {i:random.randint(j,n_cols 10) for i,j in zip(abc_vals,range(n_cols))} #map-dict
#Calculations... Formula: Σ(Xi*Yi)/ΣY
y_vals = {i:j**2 for i,j in x_map.items()} #Y's set of values to use
weights = [x_val*y_val for x_val,y_val in zip(x_map.values(),y_vals.values())] #(Xi*Yi)
result = sum(weights)/sum(y_vals.values()) #Σ(X*Y)/ΣY
return result
#Getting the parquet file
file_path = 'C:/XYZ/project/'
file_name = 'gx6c'
#pyarrow parquet -> pandas
large_pq = pq.read_table(file_path file_name '.pq').to_pandas()
#Number of columns - column per alphabet in a row:
n_columns = int(file_name.split('x')[-1].replace('c',''))
#-------------------------------------------------------Results and time taken
t.tic() #start time
#Function applied
large_pq['values'] = large_pq.apply(lambda x: val_calc(x, n_columns), axis=1)
t.toc() #end time
print(f'Time passed for applying function: {round(t.elapsed,5)} seconds')
display(large_pq)
#Querying part
t.tic()
queried = large_pq[large_pq['values'].between(12,13)]
t.toc()
print(f'Time passed for query: {round(t.elapsed,5)} seconds')
display(queried)
Вывод:
Time passed for applying function: 17.60126 seconds
abc values
0 AAAAAA 13.258228
1 AAAAAB 10.227642
2 AAAABA 11.264317
3 AAABAA 12.422303
4 AABAAA 13.537634
... ... ...
999995 JJIJJJ 12.620214
999996 JJJIJJ 11.323636
999997 JJJJIJ 10.756757
999998 JJJJJI 10.358811
999999 JJJJJJ 10.896328
1000000 rows × 2 columns
Time passed for query: 0.04801 seconds
abc values
3 AAABAA 12.422303
5 ABAAAA 12.062818
13 AAAAAD 12.762040
16 AADAAA 12.925373
25 AAAAAF 12.661267
... ... ...
999967 IJJJII 12.936667
999972 JIJIJI 12.331742
999986 JIJJJI 12.133333
999993 IJJJJJ 12.179487
999995 JJIJJJ 12.620214
284129 rows × 2 columns
Повторение того же для таблицы из 13 миллионов строк с 17 алфавитами в строке (или 17 «столбцами») заняло около 10 минут, шаг запроса 0,22524 секунды. При работе с файлами большего размера я получаю ошибки памяти, поэтому невозможно достичь отметки в миллиард строк. Возможно ли какие-либо обходные пути для выполнения процессов за гораздо меньший промежуток времени, например, 10 секунд вместо минут для таблицы из 13 миллионов строк?
Комментарии:
1. вы должны обрабатывать свои данные порциями или использовать Dask framework.
2. Помимо разбиения на фрагменты, вам нужно заменить ваши представления списка / dict массивами numpy, поскольку вы все-таки не используете ключи. Не используйте apply, создайте 1D массив numpy и назначьте его новому столбцу