Я устанавливаю массив с помощью степенного уравнения. Проблема в том, что часть моего домена пытается сделать numpy.power (x, n), когда x отрицательно и n не является целым числом. В этой части домена я хочу, чтобы значение было 0.0. Ниже приведен код с правильным поведением, но есть ли более Pythonic способ сделать это?

# note mesh.x is a numpy array of length nx
myValues = npy.zeros((nx))
para = [5.8780046, 0.714285714, 2.819250868] 
for j in range(nx):
    if mesh.x[j] > para[1]:
        myValues[j] = para[0]*npy.power(mesh.x[j]-para[1],para[2])

    else:
        myValues[j] = 0.0
2
Carl Houtman 17 Дек 2015 в 22:19

3 ответа

Лучший ответ

Является ли слово «numpythonic»? Это должно быть слово. Следующее действительно не является ни питоническим, ни непифоническим, но оно гораздо более эффективно, чем использование for цикла, и близко (r) к пути Travis, вероятно, сделает это:

import numpy
mesh_x = numpy.array([0.5,1.0,1.5])
myValues = numpy.zeros_like( mesh_x )
para = [5.8780046, 0.714285714, 2.819250868] 
mask = mesh_x > para[1]
myValues[mask] = para[0] * numpy.power(mesh_x[mask] - para[1], para[2])
print(myValues)

Для очень больших проблем вы, вероятно, захотите избежать создания временных массивов:

mask = mesh.x > para[1]
myValues[mask] = mesh.x[mask]
myValues[mask] -= para[1]
myValues[mask] **= para[2]
myValues[mask] *= para[0]
1
jez 17 Дек 2015 в 21:11

Больше объяснения ответов, данных @jez и @Divakar на простых примерах, чем сам ответ. Они оба полагаются на какую-то форму логическое индексирование.

>>> 
>>> a
array([[-4.5, -3.5, -2.5],
       [-1.5, -0.5,  0.5],
       [ 1.5,  2.5,  3.5]])
>>> n = 2.2
>>> a ** n
array([[         nan,          nan,          nan],
       [         nan,          nan,   0.21763764],
       [  2.44006149,   7.50702771,  15.73800567]])

np.where создан для этого, он выбирает одно из двух значений на основе логического массива.

>>> np.where(np.isnan(a**n), 0, a**n)
array([[  0.        ,   0.        ,   0.        ],
       [  0.        ,   0.        ,   0.21763764],
       [  2.44006149,   7.50702771,  15.73800567]])
>>> 
>>> b = np.where(a < 0, 0, a)
>>> b
array([[ 0. ,  0. ,  0. ],
       [ 0. ,  0. ,  0.5],
       [ 1.5,  2.5,  3.5]])
>>> b **n
array([[  0.        ,   0.        ,   0.        ],
       [  0.        ,   0.        ,   0.21763764],
       [  2.44006149,   7.50702771,  15.73800567]])

Используйте логическое индексирование для левой стороны и правой стороны . Это похоже на np.where

>>> 
>>> a[a >= 0] = a[a >= 0] ** n
>>> a
array([[ -4.5       ,  -3.5       ,  -2.5       ],
       [ -1.5       ,  -0.5       ,   0.21763764],
       [  2.44006149,   7.50702771,  15.73800567]])
>>> a[a < 0] = 0
>>> a
array([[  0.        ,   0.        ,   0.        ],
       [  0.        ,   0.        ,   0.21763764],
       [  2.44006149,   7.50702771,  15.73800567]])
>>>
0
wwii 17 Дек 2015 в 19:48

Вот один подход с np.where выбрать значения между вычислениями мощности и 0 -

import numpy as np
np.where(mesh.x>para[1],para[0]*np.power(mesh.x-para[1],para[2]),0)

Объяснение:

  1. np.where(mask,A,B) выбирает элементы из A или B в зависимости от mask элементов. Итак, в нашем случае это mesh.x>para[1] при выполнении векторизованного сравнения для всех mesh.x элементов за один раз.
  2. para[0]*np.power(mesh.x-para[1],para[2]) дает нам элементы, которые должны быть выбраны в случае, если маской является True. Иначе мы выбираем 0, который является третьим аргументом np.where.
1
Divakar 17 Дек 2015 в 19:31