сокращение времени для длинного цикла for в python

#python #for-loop #numpy

#python #цикл for #numpy

Вопрос:

другой глупый вопрос с моей стороны 😉 У меня возникли некоторые проблемы со следующим фрагментом с len (x) = len (y) = 7’700’000:

 from numpy import *

for k in range(len(x)):
    if x[k] == xmax:
        xind = -1
    else:
        xind = int(floor((x[k]-xmin)/xdelta))
    if y[k] == ymax:
        yind = -1
    else:
        yind = int(floor((y[k]-ymin)/ydelta))

    arr = append(arr,grid[xind,yind])
  

Все переменные являются числами с плавающей запятой, за исключением arr и grid . arr это одномерный массив и grid это 2D-массив.

Моя проблема в том, что выполнение цикла занимает много времени (несколько минут). Кто-нибудь может мне объяснить, почему это занимает так много времени? У кого-нибудь есть предложения? Даже если я попытаюсь выполнить обмен range() через arange() , я сэкономлю всего какую-то секунду.

Спасибо.

1-я ПРАВКА Извините. Забыл сказать, что я импортирую numpy

2-Я ПРАВКА

У меня есть несколько точек в 2D-сетке. В каждой ячейке сетки хранится значение. Я должен выяснить, какое положение имеет точка, и применить значение к новому массиву. Это моя проблема и моя идея.

p.s.: посмотрите на картинку, если хотите лучше ее понять. значения ячейки представлены разными цветами.

идея

Ответ №1:

Как насчет чего-то вроде:

 import numpy as np
xind = np.floor((x-xmin)/xdelta).astype(int)
yind = np.floor((y-ymin)/ydelta).astype(int)

xind[np.argmax(x)] = -1
yind[np.argmax(y)] = -1

arr = grid[xind,yind]
  

Примечание: если вы используете numpy, не обрабатывайте массивы как списки python, если хотите выполнять что-то эффективно.

Комментарии:

1. 1, особенно для «Если вы используете numpy, не обрабатывайте массивы как списки»! Однако, в качестве дополнительного примечания, np.floor((x - xmin) / xdelta) эквивалентно (x - xmin) // xdelta (и немного быстрее, не то чтобы это имело значение в данном случае.).

2. @PateToni: Нет проблем. Numpy — фантастически мощный пакет, но он требует думать о проблемах иначе, чем вы бы думали, если бы использовали другие структуры данных Python. Требуется некоторое время, чтобы переключить ваше мышление, но когда вы освоитесь с этим, вы получите огромное ускорение в своем коде по сравнению с итерацией по массивам по одному элементу за раз.

3. Есть ли какая-нибудь книга или учебник, которые могут улучшить мышление?

4.@PateToni: Я пришел из matlab, поэтому я уже привык так думать, но, вероятно, было бы неплохо просто просмотреть документацию и руководство пользователя и ознакомиться с типом доступных методов, а также взглянуть на решения других вопросов SOdocs.scipy.org/doc/numpy/reference docs.scipy.org/doc/numpy/user

Ответ №2:

 for x_item, y_item in zip(x, y):
    # do stuff.
  

Также есть izip, если вы не хотите генерировать гигантский дополнительный список.

Ответ №3:

Я не вижу очевидной проблемы, помимо размера данных. Способен ли ваш компьютер хранить все данные в памяти? Если нет, вы, вероятно, «прыгаете» в заменяемой памяти, которая всегда будет медленной. Если полные данные находятся в памяти, попробуйте psyco. Это может значительно ускорить ваши вычисления.

Ответ №4:

Я подозреваю, что проблема может быть в том, как вы сохраняете результаты:

 arr = append(arr,grid[xind,yind])
  

В документах для append говорится, что он возвращает:

Копия arr с values добавлением к axis . Обратите внимание, что append это не происходит на месте: выделяется и заполняется новый массив.

Это означает, что вы будете освобождать и выделять все больший массив с каждой итерацией. Я предлагаю заранее выделить массив правильного размера, а затем заполнять его данными на каждой итерации. например:

 arr = empty(len(x))

for k in range(len(x)):
    ...
    arr[k] = grid[xind,yind]
  

Ответ №5:

длина x составляет 7 миллионов? Я думаю, вот почему! Итерации выполняются 7 миллионов раз,

вероятно, вам следует создать цикл другого типа. Действительно необходимо выполнять цикл более 7 миллионов раз?