Ответ 1
короче, быстрее и яснее ответ, избегая сетки:
import numpy as np
def func(x, y):
return np.sin(y * x)
xaxis = np.linspace(0, 4, 10)
yaxis = np.linspace(-1, 1, 20)
result = func(xaxis[:,None], yaxis[None,:])
Это будет быстрее в памяти, если вы получите что-то вроде x ^ 2 + y в качестве функции, так как x ^ 2 выполняется в одномерном массиве (вместо 2D), и увеличение размера происходит только тогда, когда вы выполняете " +". Для meshgrid x ^ 2 будет выполняться на двумерном массиве, в котором практически все строки одинаковы, что приводит к значительному увеличению времени.
Редактировать: "x [:, None]", превращает x в двумерный массив, но с пустым вторым измерением. Это "None" - то же самое, что и "x [:, numpy.newaxis]". То же самое делается с Y, но с созданием пустого первого измерения.
Редактировать: в 3-х измерениях:
def func2(x, y, z):
return np.sin(y * x)+z
xaxis = np.linspace(0, 4, 10)
yaxis = np.linspace(-1, 1, 20)
zaxis = np.linspace(0, 1, 20)
result2 = func2(xaxis[:,None,None], yaxis[None,:,None],zaxis[None,None,:])
Таким образом, вы можете легко расширить до n измерений, если хотите, используя столько None
или :
сколько у вас есть измерений. Каждый :
создает измерение, а каждый None
создает "пустое" измерение. Следующий пример показывает немного больше, как работают эти пустые измерения. Как вы можете видеть, форма изменяется, если вы используете None
, показывая, что в следующем примере это 3D-объект, но пустые измерения заполняются только тогда, когда вы умножаетесь на объект, который действительно имеет что-то в этих измерениях (звучит сложно, но следующий пример показывает, что я имею в виду)
In [1]: import numpy
In [2]: a = numpy.linspace(-1,1,20)
In [3]: a.shape
Out[3]: (20,)
In [4]: a[None,:,None].shape
Out[4]: (1, 20, 1)
In [5]: b = a[None,:,None] # this is a 3D array, but with the first and third dimension being "empty"
In [6]: c = a[:,None,None] # same, but last two dimensions are "empty" here
In [7]: d=b*c
In [8]: d.shape # only the last dimension is "empty" here
Out[8]: (20, 20, 1)
редактировать: без необходимости набирать None самостоятельно
def ndm(*args):
return [x[(None,)*i+(slice(None),)+(None,)*(len(args)-i-1)] for i, x in enumerate(args)]
x2,y2,z2 = ndm(xaxis,yaxis,zaxis)
result3 = func2(x2,y2,z2)
Таким образом, вы делаете None
-slicing для создания дополнительных пустых измерений, делая первый аргумент, который вы даете ndm как первое полное измерение, а второй как второе полное измерение etc- делает то же самое, что и "жестко закодированный" Нетипизированный синтаксис, используемый ранее.
Краткое объяснение: выполнение x2, y2, z2 = ndm(xaxis, yaxis, zaxis)
аналогично выполнению
x2 = xaxis[:,None,None]
y2 = yaxis[None,:,None]
z2 = zaxis[None,None,:]
но метод ndm также должен работать для большего количества измерений, без необходимости жестко кодировать None
-slices в несколько строк, как только что показано. Это также будет работать в numpy версиях до 1.8, в то время как numpy.meshgrid работает только для более чем 2-х измерений, если у вас numpy 1.8 или выше.