Принимая среднее значение numpy ndarray с элементами в масках

1

У меня есть массив значений MxN, взятый из эксперимента. Некоторые из этих значений являются недопустимыми и для них указывается 0. Я могу создать маску действительных/недопустимых значений, используя

mask = (mat1 == 0) & (mat2 == 0)

который создает массив MxN из bool. Следует отметить, что маскированные местоположения не аккуратно следуют за столбцами или строками матрицы - так что просто обрезка матрицы не является вариантом.

Теперь я хочу взять среднее значение вдоль одной оси моего массива (EG заканчивается массивом 1xN), исключая эти недопустимые значения в среднем вычислении. Интуитивно я подумал

 np.mean(mat1[mask],axis=1)

должен сделать это, но mat1[mask] создает 1D-массив, который, по-видимому, является только тем элементом, где mask является истиной, что не помогает, когда мне нужно только среднее значение для одного измерения массива.

Есть ли способ "python-esque" или numpy для этого? Я предполагаю, что могу использовать маску для установки маскированных элементов в NaN и использовать np.nanmean - но это все еще кажется неуклюжим. Есть ли способ сделать это "чисто"?

Теги:
arrays
numpy
mask

2 ответа

1
Лучший ответ

Я думаю, что лучший способ сделать это - это нечто вроде:

masked = np.ma.masked_where(mat1 == 0 && mat2 == 0, array_to_mask)

Затем возьмите среднее значение с

masked.mean(axis=1)
  • 1
    Работал отлично! Я не знал о массивах в масках - спасибо!
1

Один такой же неуклюжий, но эффективный способ состоит в том, чтобы умножить ваш массив на маску, установив маскированные значения в ноль. Тогда, конечно, вам придется разделить на количество незамаскированных значений вручную. Отсюда и неуклюжесть. Но это будет работать с целочисленными массивами, что нельзя сказать о случае nan. Он также кажется самым быстрым как для небольших, так и для больших массивов (в том числе решение маскированного массива в другом ответе):

import numpy as np

def nanny(mat, mask):
    mat = mat.astype(float).copy() # don't mutate the original
    mat[~mask] = np.nan            # mask values
    return np.nanmean(mat, axis=0) # compute mean

def manual(mat, mask):
    # zero masked values, divide by number of nonzeros
    return (mat*mask).sum(axis=0)/mask.sum(axis=0)

# set up dummy data for testing
N,M = 400,400
mat1 = np.random.randint(0,N,(N,M))
mask = np.random.randint(0,2,(N,M)).astype(bool)

print(np.array_equal(nanny(mat1, mask), manual(mat1, mask))) # True

Ещё вопросы

Сообщество Overcoder
Наверх
Меню