Добавление массивов, которые могут содержать None-записи - PullRequest
0 голосов
/ 26 апреля 2018

У меня есть вопрос относительно добавления массивов numpy. Давайте предположим, что я определил функцию

def foo(a,b):
    return a+b

, который принимает два массива одинаковой формы и просто возвращает их сумму. Теперь я должен разобраться со случаями, когда некоторые записи могут быть Нет. Я хотел бы иметь дело с этими записями, так как они соответствуют float (0), так что

[1.0,None,2.0] + [1.0,2.0,2.0] 

составит в сумме

[2.0,2.0,4.0]

Можете ли вы предоставить мне уже реализованное решение?

TIA

Ответы [ 3 ]

0 голосов
/ 26 апреля 2018

Я предлагаю numpy.nan_to_num:

>>> np.nan_to_num(np.array([1.0,None,2.0], dtype=np.float))
array([ 1.,  0.,  2.])

Тогда

>>> def foo(a,b):
...         return np.nan_to_num(a) + np.nan_to_num(b)
...
>>> foo(np.array([1.0,None,2.0], dtype=np.float), np.array([1.0,2.0,2.0], dtype=np.float))
array([ 2.,  0.,  4.])
0 голосов
/ 26 апреля 2018

Обычно ответом на это является использование массива с плавающей точкой, а не массива произвольных объектов, а затем использование np.nan вместо None. NaN имеет четко определенную семантику для арифметики. (Кроме того, использование массива с плавающей точкой вместо объектов сделает ваш код значительно более эффективным с точки зрения времени и пространства.)


Обратите внимание, что вам не нужно вручную преобразовывать None в np.nan, если вы строите массив с явным dtype из float или np.float64. Оба они эквивалентны:

>>> a = np.array([1.0,np.nan,2.0])
>>> a = np.array([1.0,None,2.0],dtype=float)

Это означает, что если по какой-то причине вам действительно нужны массивы произвольных объектов с действительным None, вы можете сделать это, а затем преобразовать его в массив с плавающей точкой на лету, чтобы получить преимущества от NaN :

>>> a.astype(float) + b.astype(float)

В любом случае, в данном случае просто использования NaN недостаточно:

>>> a = np.array([1.0,np.nan,2.0])
>>> b = np.array([1.0,2.0,2.0])
>>> a + b
array([ 2., nan,  4.])

Это потому, что семантика NaN заключается в том, что результат любой операции с NaN возвращает NaN. Но вы хотите рассматривать это как 0.

Но это делает проблему легко решаемой. Самый простой способ решить это с помощью функции nan_to_num:

>>> np.nan_to_num(a, 0)
array([1., 0., 2.0])
>>> np.nan_to_num(a, 0) + np.nan_to_num(b, 0)
array([2., 2., 4.])
0 голосов
/ 26 апреля 2018

Вы можете использовать column_stack для объединения обоих массивов вдоль второй оси, а затем использовать np.nansum() для суммирования элементов по второй оси.

In [15]: a = np.array([1.0,None,2.0], dtype=np.float)
# Using dtype here is necessary to convert None to np.nan

In [16]: b = np.array([1.0,2.0,2.0]) 

In [17]: np.nansum(np.column_stack((a, b)), 1)
Out[17]: array([2., 2., 4.])
...