#python-3.x #for-loop #nested-loops
Вопрос:
У меня есть вложенный цикл, который должен проходить через огромное количество данных.
Предполагая,что фрейм данных со случайными значениями размером 1000 000 строк каждый имеет расположение X, Y в 2D-пространстве. Существует окно длиной 10, которое поочередно просматривает все строки данных размером 1 м, пока не будут выполнены все вычисления.
Объяснение того, что должен делать код:
- Каждая строка представляет координаты в плоскости X-Y.
r_test
содержит диаметры различных кругов исследований в нашей двумерной плоскости (плоскость X-Y).- Для каждых 10 точек/строк, для каждого отдельного диаметра в
r_test
, мы сравниваем расстояние между каждой точкой с оставшимися 9 точками, и если значение меньше R, мы добавляем 2H
. Затем мы вычисляемH/(N**5)
и сохраняем егоc_10
с индексом, соответствующим диаметру исследования. - Для этих первых 10 точек , наконец, когда петля прошла все эти диаметры
r_test
, мы считываем наклон установленной линии и сохраняем егоS_wind[ii]
. Таким образом, первые 9 точек данных не будут иметь никакого значения, рассчитанного для них, что позволит ихnp.inf
отличить позже. - Затем окно перемещается на одну точку вниз по строкам и повторяет этот процесс до
S_wind
тех пор, пока не будет завершено.
Какой потенциально лучший алгоритм для решения этой проблемы, чем тот, который я использую? в python 3.x?
Заранее большое спасибо!
import numpy as np
import pandas as pd
####generating input data frame
df = pd.DataFrame(data = np.random.randint(2000, 6000, (1000000, 2)))
df.columns= ['X','Y']
####====creating upper and lower bound for the diameter of the investigation circles
x_range =max(df['X']) - min(df['X'])
y_range = max(df['Y']) - min(df['Y'])
R = max(x_range,y_range)/20
d = 2
N = 10 #### Number of points in each window
#r1 = 2*R*(1/N)**(1/d)
#r2 = (R)/(1 d)
#r_test = np.arange(r1, r2, 0.05)
##===avoiding generation of empty r_test
r1 = 80
r2= 800
r_test = np.arange(r1, r2, 5)
S_wind = np.zeros(len(df['X'])) np.inf
for ii in range (10,len(df['X'])): #### maybe the code run slower because of using len() function instead of a number
c_10 = np.zeros(len(r_test)) np.inf
H = 0
C = 0
N = 10 ##### maybe I should also remove this
for ind in range(len(r_test)):
for i in range (ii-10,ii):
for j in range(ii-10,ii):
dd = r_test[ind] - np.sqrt((df['X'][i] - df['X'][j])**2 (df['Y'][i] - df['Y'][j])**2)
if dd > 0:
H = 1
c_10[ind] = (H/(N**2))
S_wind[ii] = np.polyfit(np.log10(r_test), np.log10(c_10), 1)[0]
Комментарии:
1. Было бы очень полезно, если бы вы объяснили, что ваш код должен был делать со всеми этими точками данных. Я озадачен целым рядом вещей, и я даже не добрался до вложенного цикла, о котором вы спрашиваете. Почему вы берете пятый корень из 1/10 и используете кратное ему в качестве нижней границы диапазона? Лучшие имена переменных могут стать началом того, чтобы сделать код более понятным.
2. @Blckknight Спасибо за ваш комментарий. Мои извинения, я попытаюсь очистить код сейчас.
3. @Blckknight Я попытался объяснить, что должен делать код. Помогает ли это вам понять назначение кода? Пожалуйста, дайте мне знать, если мне нужно будет уточнить больше. Большое спасибо!
4. Поэтому я пытаюсь протестировать способ использования широковещательной передачи numpy для устранения трех внутренних циклов, но я обнаружил, что
r_test
это пустой массив для моих случайных данных. Это то, что должно быть возможно, или вычисления как-то неверны?5. @Blckknight Спасибо за комментарий. Нет, на самом деле он не должен быть пустым. Я изменил код таким образом, чтобы избежать каких-либо пустых
r_test
. Этот код похож на мой реальный код, за исключением того, что данные здесь генерируются случайным образом, а длина окна составляет всего 10, а в моем случае-200.
Ответ №1:
Вы можете использовать numpy
широковещание для устранения всех внутренних циклов. Я не уверен, что есть простой способ избавиться от самой внешней петли, но других не так уж трудно избежать.
Внутренние петли сравнивают десять 2D-точек друг с другом попарно. Это просто смерть за использование массива numpy 10x10x2:
# replacing the `for ind` loop and its contents:
points = np.hstack((np.asarray(df['X'])[ii-10:ii, None], np.asarray(df['Y'])[ii-10:ii, None]))
differences = np.subtract(points[None, :, :], points[:, None, :]) # broadcast to 10x10x2
squared_distances = (differences * differences).sum(axis=2)
within_range = squared_distances[None,:,:] < (r_test*r_test)[:, None, None] # compare squares
c_10 = within_range.sum(axis=(1,2)).cumsum() * 2 / (N**2)
S_wind[ii] = np.polyfit(np.log10(r_test), np.log10(c_10), 1)[0] # this is unchanged...
Я не очень pandas
сообразителен, поэтому, вероятно, есть лучший способ собрать значения X и Y в один 2-мерный массив numpy. Вы сгенерировали случайные данные в формате, который я нахожу наиболее полезным, а затем преобразовали во что-то менее полезное для числовых операций!
Обратите внимание, что этот код совпадает с выводом вашего кода цикла. Я не уверен, что это на самом деле делает то, что вы хотите, так как в вашем текущем коде есть несколько немного странных вещей. Например, вам может не понадобиться cumsum
в моем коде, что соответствует только повторной инициализации H
до нуля во внешнем цикле. Если вы не хотите, чтобы совпадения для меньших значений r_test
снова подсчитывались для больших значений, вы можете пропустить эту сумму (или, что эквивалентно, переместить H = 0
строку между циклами for ind
и for i
циклами в исходном коде).