2017-04-11 78 views
2

我有一些数组A,并且数组的相应元素包含每行的bin分配。我想构建一个阵列S,这样添加numpy数组元素/切片具有相同的bin分配

S[0, :] = (A[(bins == 0), :]).sum(axis=0) 

这是相当容易做到np.stack和列表理解,但似乎过于复杂,不是非常可读。是否有一种更一般的方法来加总(或者甚至应用一些通用函数)带有分配分配的数组切片? scipy.stats.binned_statistic沿着正确的线条,但要求用于计算函数的bin赋值和值是相同的形状(因为我正在使用切片,情况并非如此)。

例如,如果

A = np.array([[1., 2., 3., 4.], 
       [2., 3., 4., 5.], 
       [9., 8., 7., 6.], 
       [8., 7., 6., 5.]]) 

bins = np.array([0, 1, 0, 2]) 

那么就应该引起

S = np.array([[10., 10., 10., 10.], 
       [2., 3., 4., 5. ], 
       [8., 7., 6., 5. ]]) 

回答

2

下面是使用np.dotmatrix-multiplication的方法 -

(bins == np.arange(bins.max()+1)[:,None]).dot(A) 

采样运行 -

In [40]: A = np.array([[1., 2., 3., 4.], 
    ...:    [2., 3., 4., 5.], 
    ...:    [9., 8., 7., 6.], 
    ...:    [8., 7., 6., 5.]]) 

In [41]: bins = np.array([0, 1, 0, 2]) 

In [42]: (bins == np.arange(bins.max()+1)[:,None]).dot(A) 
Out[42]: 
array([[ 10., 10., 10., 10.], 
     [ 2., 3., 4., 5.], 
     [ 8., 7., 6., 5.]]) 

性能提升

一种更有效的方式来创建蒙(bins == np.arange(bins.max()+1)[:,None]),会像这样 -

mask = np.zeros((bins.max()+1, len(bins)), dtype=bool) 
mask[bins, np.arange(len(bins))] = 1 
+1

这比@ Psidom的解决方案快大约30%,所以接受这一点。这对我来说稍微直截了当,但都起作用。 – DathosPachy

2

您可以使用np.add.reduceat

import numpy as np 
# index to sort the bins 
sort_index = bins.argsort() 

# indices where the array needs to be split at 
indices = np.concatenate(([0], np.where(np.diff(bins[sort_index]))[0] + 1)) 

# sum values where the bins are the same 
np.add.reduceat(A[sort_index], indices, axis=0) 

# array([[ 10., 10., 10., 10.], 
#  [ 2., 3., 4., 5.], 
#  [ 8., 7., 6., 5.]])