Я создал набор тестовых данных с 6 миллионами строк, но только 2 столбцами, и рассчитал время для нескольких методов выборки (два, которые вы опубликовали, плюс df.sample
с параметром n
). Для каждого метода выборка заняла немногим более 200 мс, что, на мой взгляд, достаточно быстро. В моем наборе данных значительно меньше столбцов, поэтому это может быть причиной, тем не менее, я думаю, что ваша проблема вызвана не самой выборкой, а загрузкой данных и хранением их в памяти.
Я не использовал Dask раньше, но я предполагаю, что он использует некоторый logi c для кэширования данных с диска или сетевого хранилища. В зависимости от шаблонов доступа может случиться так, что кеширование работает не очень хорошо, и фрагменты данных должны загружаться из потенциально медленного хранилища для каждого отобранного образца.
Если поддерживается Dask , возможное решение может заключаться в том, чтобы нарисовать индексы записей набора выборочных данных (как в вашем втором методе) до фактической загрузки всего набора данных и загрузить только выбранные записи. Это вариант?
Обновление:
Dask утверждает, что выборки по строкам, например df[df.x > 0]
, могут быть вычислены быстро / параллельно (https://docs.dask.org/en/latest/dataframe.html). Может, можно попробовать что-то вроде этого:
sampled_indices = random.sample(range(len(df)), NSAMPLES)
df_s = df[df.index in sampled_indices]
Вот код, который я использовал для определения времени и некоторых результатов:
import numpy as np
import pandas as pd
import random
import timeit
data = {
's_val' : list(),
'f_val' : list()}
for i in range(int(6e6)):
data['s_val'].append('item #' + str(i))
data['f_val'].append(random.random())
df = pd.DataFrame(data)
NSAMPLES = 5000
NRUNS = 50
methods = [
lambda : df.sample(n=NSAMPLES, replace=None, random_state=10),
lambda : df.sample(frac=NSAMPLES/len(df), replace=None, random_state=10),
lambda : df.loc[np.random.choice(df.index, size=NSAMPLES, replace=False)],
]
for i, f in enumerate(methods):
print('avg. time method {}: {} s'.format(
i, timeit.timeit(methods[i], number=NRUNS) / NRUNS))
Примерные результаты:
avg. time method 0: 0.21715480241997284 s
avg. time method 1: 0.21541569983994122 s
avg. time method 2: 0.21495854450011392 s