Как уменьшить использование памяти этим фрагментом кода и повысить его скорость? - PullRequest
0 голосов
/ 13 марта 2019

Я запускаю цикл for, который зацикливается на всех строках кадра данных pandas, затем вычисляет евклидово расстояние от одной точки за раз до всех других точек в кадре данных, затем проходит следующую точку и сделать то же самое и т. д.

Дело в том, что мне нужно хранить значения значений расстояний, чтобы позже построить гистограмму, я храню это в другом кадре данных панд. Проблема в том, что по мере увеличения второго информационного кадра в какой-то момент времени у меня кончится память. Не говоря уже о том, что по мере увеличения размера фрейма данных повторение этого же цикла будет выполняться медленнее, поскольку он будет тяжелее и сложнее обрабатывать в памяти.

Вот несколько игрушечных данных для воспроизведения оригинальной задачи:

import pandas as pd

xx = []
yy = []
tt = []

for i in progressbar(range(1,655556)):
    xx.append(i)
    yy.append(i)
    tt.append(i)

df = pd.DataFrame()
df['xx'] = xx
df['yy'] = yy
df['tt'] = tt
df['xx'] = df['xx'].apply(lambda x : float(x))
df['yy'] = df['yy'].apply(lambda x : float(x))
df['tt'] = df['tt'].apply(lambda x : float(x))
df

Это оригинальный фрагмент кода, который я использовал:

counts = pd.DataFrame()

for index, row in df.iterrows():

    dist = pd.Series(np.sqrt((row.xx - df.xx)**2 + (row.yy - df.yy)**2 + (row.tt - df.tt)**2))
    counter = pd.Series(dist.value_counts( sort = True)).reset_index().rename(columns = {'index': 'values', 0:'counts'})   
    counts = counts.append(counter)

Исходный df имеет форму (695556, 3), поэтому ожидаемый результат должен быть кадром данных формы (695556**3, 2), содержащим все значения расстояния от всех 3 векторов и их количество. Проблема в том, что это невозможно вписаться в мой 16 ГБ оперативной памяти.

Так что я пробовал это вместо:

for index, row in df.iterrows():
    counts = pd.DataFrame()
    dist = pd.Series(np.sqrt((row.xx - df.xx)**2 + (row.yy - combination.yy)**2 + (row.tt - df.tt)**2))
    counter = pd.Series(dist.value_counts( sort = True)).reset_index().rename(columns = {'index': 'values', 0:'counts'})   
    counts = counts.append(counter)
    counts.to_csv('counts/count_' + str(index) + '.csv')
    del counts

В этой версии вместо того, чтобы просто хранить кадры данных в памяти, я пишу CSV для каждого цикла. Идея состоит в том, чтобы собрать все вместе позже, когда он закончится. Этот код работает быстрее, чем первый, поскольку время для каждого цикла не будет увеличиваться по мере увеличения размера кадра данных. Хотя, это все еще медленно, так как он должен писать CSV каждый раз. Не сказать, что это будет еще медленнее, когда мне придется читать все эти CSV-файлы в одном кадре данных.

Может кто-нибудь показать мне, как я могу оптимизировать этот код для достижения тех же результатов, но более быстрым и более эффективным способом памяти ?? Я также открыт для других реализаций, таких как spark, dask или любой другой способ достижения того же результата: информационный кадр, содержащий значение, учитывает все расстояния, но это может быть более или менее удобным с точки зрения времени и памяти.

Заранее большое спасибо

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...