numpy: среднее значение для разных подмножеств каждой строки в матрице - PullRequest
1 голос
/ 14 марта 2020

Учитывая следующую матрицу

In [1]: a
Out[1]: 
array([[106.74    , 108.072   , 108.72    , 109.584   , 108.468   ],
       [114.012   , 114.156   , 107.928   , 113.904   , 112.968   ],
       [114.396225, 115.21124 , 116.01796 , 115.0901  , 113.01843 ]],
      dtype=float32)

Я могу вычислить среднее значение для каждого поднабора строк следующим образом:

In [2]: np.mean(a[:,1:3],axis=1)
Out[2]: array([108.395996, 111.042   , 115.6146  ], dtype=float32)

Но то, что я пытаюсь сделать сейчас, это следующее ,

с учетом набора индексов i = [3,4,3]

Я хочу иметь средства

a[0,1:3]

a[1,1:4]

a[3,1:2]

соответственно,

, поэтому, естественно, мой первый попытка была,

In [2]: np.mean(a[:,1:i],axis=1)
TypeError: slice indices must be integers or None or have an __index__ method

, которая, конечно, не работает.

Я также знаю об этом,

In [3]: a[np.where(i)+(i,)]
Out[3]: array([108.468 , 113.904 , 115.0901], dtype=float32)

Но мне не удалось выяснить, как объединить их ....

Есть идеи?

обновить после ответов @ luciole75w и @Friedrich,

Я сравниваю время выполнения для обеих версий,

print(a.shape,ii.shape)
#
t = time.time()
mu1b=np.array([np.mean(a[j,0:i]) for j,i in enumerate(ii)])
print(time.time() - t)
# 
t = time.time()
col = np.arange(a.shape[1]).reshape(-1, 1)
istart = 0         # or variable, e.g. istart = [1, 1, 1]
istop = ii  # or fixed, e.g. istop = 3
tmask = (istart <= col) & (col < istop)
mu1 = np.nansum(a.T*tmask,axis=0)/tmask.sum(axis=0)
print(time.time() - t)

приводит к тому, что

(740832, 30) (740832,)
7.258646249771118
0.5934605598449707

@ luciole75w версия, основанная на предложении @AndrasDeak, намного эффективнее.

Ответы [ 2 ]

1 голос
/ 14 марта 2020

Вы можете использовать выражение генератора

a = np.array([[106.74    , 108.072   , 108.72    , 109.584   , 108.468   ],
              [114.012   , 114.156   , 107.928   , 113.904   , 112.968   ],
              [114.396225, 115.21124 , 116.01796 , 115.0901  , 113.01843 ]])

[np.mean(a[j,1:i]) for j,i in zip([0,1,2],[3,4,2])]

Возвращает: [108.396, 111.996, 114.156].

Массивы предназначены для работы со строками и столбцами одинаковой длины. Но с вашими конечными индексами вы имеете в виду строки различной длины.

1 голос
/ 14 марта 2020

Хорошая идея от Андраса, я бы тоже использовал тот же подход. Маска может быть построена с чем-то вроде:

istart = 1         # or variable, e.g. istart = [1, 2, 1]
istop = [3, 4, 3]  # or fixed, e.g. istop = 3

col = np.arange(a.shape[1]).reshape(-1, 1)

tmask = (istart <= col) & (col < istop)
#array([[False, False, False],
#       [ True,  True,  True],
#       [ True,  True,  True],
#       [False,  True, False],
#       [False, False, False]], dtype=bool)

np.where(tmask, a.T, 0).sum(axis=0) / tmask.sum(axis=0)

array([ 108.396 ,  111.996 ,  115.6146])

Обратите внимание, что маска транспонирована так, что входные границы могут быть легко записаны с использованием собственных типов python (так как они применяются вдоль ось 0).

...