Переопределите значения с помощью нескольких операторов if Numpy - PullRequest
0 голосов
/ 13 февраля 2019

У меня есть большой Numpy ndarray, вот пример этого:

myarray = np.array([[1.01,9.4,0.0,6.9,5.7],[1.9,2.6,np.nan,4.7,-2.45],[np.nan,0.2,0.3,4.2,15.1]])
myarray

array([[ 1.01,  9.4 ,  0.0 ,  6.9 ,  5.7 ],
       [ 1.9 ,  2.6 ,   nan,  4.7 ,  -2.45],
       [  nan,  0.2 ,  0.3 ,  4.2 , 15.1 ]])

Как вы можете видеть, мой массив содержит числа с плавающей запятой, положительные, отрицательные, нули и NaN.Я хотел бы переназначить (переклассифицировать) значения в массиве на основе нескольких операторов if.Я прочитал много ответов и документов, но все, что я видел, относятся к простому одному или двум условиям, которые могут быть легко решены, например, с помощью np.where.У меня есть несколько условий, для простоты, скажем, у меня есть четыре условия (желаемое решение должно быть в состоянии обрабатывать больше условий).Мои условия:

if x > 6*y:
    x=3
elif x < 4*z:
    x=2
elif x == np.nan:
    x=np.nan # maybe pass is better?
else: 
    x=0

, где x - это значение в массиве, y и z - переменные, которые будут меняться среди массивов.Например, массив № 1 будет иметь y = 5, z = 2, массив № 2 будет иметь y = 0,9, z = 0,5 и т. Д. Условие для np.nan просто означает, что если значение равно nan, не изменяйте его,оставьте его в порядке.

Обратите внимание, что это необходимо выполнить одновременно, потому что если я использую несколько np.where один за другим, то условие № 2 перезапишет условие # 1.

* 1013Я пытался создать функцию, а затем применить ее к массиву, но безуспешно.Похоже, что для применения функции к массиву функция должна содержать только один аргумент (массив), и если я собираюсь использовать функцию, она должна содержать 3 аргумента: массив и значения y и z.

Какой самый эффективный способ достичь моей цели?

1 Ответ

0 голосов
/ 14 февраля 2019
In [11]: myarray = np.array([[1.01,9.4,0.0,6.9,5.7],[1.9,2.6,np.nan,4.7,-2.45],[
    ...: np.nan,0.2,0.3,4.2,15.1]])
In [13]: y, z = 0.9, 0.5

Если я выполню один из ваших тестов для всего массива:

In [14]: mask1 = myarray >6*y
/usr/local/bin/ipython3:1: RuntimeWarning: invalid value encountered in greater

Это np.nan, которое вызывает это предупреждение.

Итак, давайте сначала определим эти nan (и заменить):

In [25]: mask0 = np.isnan(myarray)
In [26]: mask0
Out[26]: 
array([[False, False, False, False, False],
       [False, False,  True, False, False],
       [ True, False, False, False, False]])
In [27]: arr = myarray.copy()
In [28]: arr[mask0] = 0     # temp replace the nan with 0

myarray == np.nan не работает;он производит False везде.

arr = np.nan_to_num(myarray) также работает, заменяя nan на 0.

Теперь найдите маски для тестов y и z.Неважно, как они обрабатывают оригинал nan (теперь 0).Сначала вычислите обе маски, чтобы уменьшить взаимные помехи.

In [29]: mask1 = arr > 6*y
In [30]: mask2 = arr < 4*z
In [31]: arr[mask1]
Out[31]: array([ 9.4,  6.9,  5.7, 15.1])
In [32]: arr[mask2]
Out[32]: array([ 1.01,  0.  ,  1.9 ,  0.  , -2.45,  0.  ,  0.2 ,  0.3 ])
In [33]: arr[mask0]
Out[33]: array([0., 0.])

Поскольку вы хотите, чтобы все остальное было равно 0, давайте инициализируем массив нулей:

In [34]: res = np.zeros_like(arr)

Теперь примените 3 маски:

In [35]: res[mask1] = 3
In [36]: res[mask2] = 2
In [37]: res[mask0] = np.nan
In [38]: res
Out[38]: 
array([[ 2.,  3.,  2.,  3.,  3.],
       [ 2.,  0., nan,  0.,  2.],
       [nan,  2.,  2.,  0.,  3.]])

Я мог бы применить маски к arr:

In [40]: arr[mask1] = 3        # np.where(mask1, 3, arr) should also work
In [41]: arr[mask2] = 2
In [42]: arr[mask0] = np.nan
In [43]: arr
Out[43]: 
array([[2. , 3. , 2. , 3. , 3. ],
       [2. , 2.6, nan, 4.7, 2. ],
       [nan, 2. , 2. , 4.2, 3. ]])

Мне все еще нужно использовать некоторую логику, чтобы объединить маски, чтобы идентифицировать слоты, которые должны быть равны 0.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...