#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 миллионов раз?