Заменить хвост ndarray в зависимости от состояния

У меня есть многомерный массив. Как только оно будет иметь критическое значение в последнем измерении, я хотел бы изменить хвост измерения.

np.random.seed(100)
arr = np.random.uniform(size=100).reshape([2,5,2,5])
# array([[[[ 0.54340494,  0.27836939,  0.42451759,  0.84477613,  0.00471886],
#          [ 0.12156912,  0.67074908,  0.82585276,  0.13670659,  0.57509333]],
#         [[ 0.89132195,  0.20920212,  0.18532822,  0.10837689,  0.21969749],
#          [ 0.97862378,  0.81168315,  0.17194101,  0.81622475,  0.27407375]],
#         [[ 0.43170418,  0.94002982,  0.81764938,  0.33611195,  0.17541045],
#          [ 0.37283205,  0.00568851,  0.25242635,  0.79566251,  0.01525497]],
#         [[ 0.59884338,  0.60380454,  0.10514769,  0.38194344,  0.03647606],
#          [ 0.89041156,  0.98092086,  0.05994199,  0.89054594,  0.5769015 ]],
#         [[ 0.74247969,  0.63018394,  0.58184219,  0.02043913,  0.21002658],
#          [ 0.54468488,  0.76911517,  0.25069523,  0.28589569,  0.85239509]]],
#        [[[ 0.97500649,  0.88485329,  0.35950784,  0.59885895,  0.35479561],
#          [ 0.34019022,  0.17808099,  0.23769421,  0.04486228,  0.50543143]],
#         [[ 0.37625245,  0.5928054 ,  0.62994188,  0.14260031,  0.9338413 ],
#          [ 0.94637988,  0.60229666,  0.38776628,  0.363188  ,  0.20434528]],
#         [[ 0.27676506,  0.24653588,  0.173608  ,  0.96660969,  0.9570126 ],
#          [ 0.59797368,  0.73130075,  0.34038522,  0.0920556 ,  0.46349802]],
#         [[ 0.50869889,  0.08846017,  0.52803522,  0.99215804,  0.39503593],
#          [ 0.33559644,  0.80545054,  0.75434899,  0.31306644,  0.63403668]],
#         [[ 0.54040458,  0.29679375,  0.1107879 ,  0.3126403 ,  0.45697913],
#          [ 0.65894007,  0.25425752,  0.64110126,  0.20012361,  0.65762481]]]])

Допустим, критическое значение будет 0.80, Нам нужно поменять все дополнительные значения после того, как мы увидим значение выше, чем 0.80, Мы сосредоточимся на двух первых "рядах". Который обозначает [3,2] после выбора с np.argmax,

where_bigger = np.argmax(arr >= 0.80, axis = 3)
# array([[[3, 2], ## used as example later !!!!!!!!!
#         [0, 0],
#         [1, 0],
#         [0, 0],
#         [0, 4]],
#        [[0, 0],
#         [4, 0],
#         [3, 0],
#         [3, 1],
#         [0, 0]]])

Как пример, мы сначала сосредоточимся на элементе с индексом 3 в [3,2](см. выше с!!!!). Как только мы нашли значение выше, чем 0.80 (индекс таков 3) все следующие значения следует заменить на np.na

arr[0,0,0,3] ## 0.84477613 comes as first element in [3,2]
# [ 0.54340494,  0.27836939,  0.42451759,  0.84477613,  np.na]

Похоже здесь, мы ориентируемся на элемент 2 снаружи [3,2] и нужно установить все следующие элементы в np.na

arr[0,0,1,2] ## 0.82585276 comes as second element in [3,2]
# [ 0.12156912,  0.67074908,  0.82585276,  np.na,  np.na]

В конце мы повторим это для всех элементов, найденных argmax:

# array([[[[ 0.54340494,  0.27836939,  0.42451759,  0.84477613,  np.na],
#          [ 0.12156912,  0.67074908,  0.82585276,       np.na,  np.na]],
#         [[ 0.89132195,       np.na,       np.na,       np.na,  np.na],
#          [ 0.97862378,       np.na,       np.na,       np.na,  np.na]],
#         [[ 0.43170418,  0.94002982,       np.na,       np.na,  np.na],
# ...

Можно ли настроить весь массив сразу без циклов? Вероятно, это можно сделать с нарезкой. Я хотел бы использовать такой подход, как arr[where_bigger:] = np.na, но это явно неправильно. И до сих пор я не мог прогрессировать дальше.

1 ответ

Решение

Лучшая ставка - это тип логической маски. Вы можете сделать tail от np.logical_or.accumulate но это будет включать в себя индекс с пороговым значением. Если вы хотите сохранить первый экземпляр, вам придется его дополнить.

mask = np.c_[np.zeros(arr.shape[:-1] + (1,), dtype = bool), np.logical_or.accumulate(arr > .8, axis = -1)[...,:-1]]
arr[mask] = np.nan
Другие вопросы по тегам