2016-11-14 15 views
8

Iは2D numpyの配列を有している。、A Iは元の行列Aの各列のbincountsから構成されている別の2DアレイBを生成するために行列Aの各列にnp.bincount()を適用します。ベクトル化numpyののbincount

私の問題は、np.bincount()は1dのような配列を取る関数だということです。例えばB = A.max(axis=1)のような配列メソッドではありません。

厄介なfor-loop以外のこのB配列を生成するために、より多くのpythonic/numpythic方法がありますか?

import numpy as np 

states = 4 
rows = 8 
cols = 4 

A = np.random.randint(0,states,(rows,cols)) 
B = np.zeros((states,cols)) 

for x in range(A.shape[1]): 
    B[:,x] = np.bincount(A[:,x]) 

答えて

2

私は、あなたがより高い次元配列の1次元スライスに(この場合はnp.bincount中)1D-法を適用することができるようになる、np.apply_along_axisを使用することをお勧め:

import numpy as np 

states = 4 
rows = 8 
cols = 4 

A = np.random.randint(0,states,(rows,cols)) 
B = np.zeros((states,cols)) 

B = np.apply_along_axis(np.bincount, axis=0, arr=A) 

あなたが持っているでしょうしかし、注意してください。これは(for -loopと同様に)np.bincountの出力が正しい形になっている場合にのみ機能します。最大状態が配列Aの1つまたは複数の列に存在しない場合、出力はより小さな次元を持たないので、コードはValueErrorでファイルされます。

+1

注意はただの構文ですfor-loopのための砂糖、そして同じ性能特性を持っています。 –

1

numpy_indexedパッケージ(免責事項:私は著者です)を使用したこのソリューションは完全にベクトル化されているため、背後にあるPythonループは含まれていません。また、入力に制限はありません。すべての列が同じ固有値セットを含む必要はありません。これは、B配列が実際に多くのゼロを含む場合、はるかに適切であり得る別の同じ結果(スパース)表現、与え

import numpy_indexed as npi 
rowidx, colidx = np.indices(A.shape) 
(bin, col), B = npi.count_table(A.flatten(), colidx.flatten()) 

:apply_along_axis

(bin, col), count = npi.count((A.flatten(), colidx.flatten())) 

注だけ糖衣構文でありますforループの場合と同じパフォーマンス特性を持ちます。

3

this postと同じ哲学を使用して、ここではベクトル化のアプローチだ -

m = A.shape[1]  
n = A.max()+1 
A1 = A + (n*np.arange(m)) 
out = np.bincount(A1.ravel(),minlength=n*m).reshape(m,-1).T 
1

さらに別の可能性:

import numpy as np 


def bincount_columns(x, minlength=None): 
    nbins = x.max() + 1 
    if minlength is not None: 
     nbins = max(nbins, minlength) 
    ncols = x.shape[1] 
    count = np.zeros((nbins, ncols), dtype=int) 
    colidx = np.arange(ncols)[None, :] 
    np.add.at(count, (x, colidx), 1) 
    return count 

例えば、apply_along_axis

In [110]: x 
Out[110]: 
array([[4, 2, 2, 3], 
     [4, 3, 4, 4], 
     [4, 3, 4, 4], 
     [0, 2, 4, 0], 
     [4, 1, 2, 1], 
     [4, 2, 4, 3]]) 

In [111]: bincount_columns(x) 
Out[111]: 
array([[1, 0, 0, 1], 
     [0, 1, 0, 1], 
     [0, 3, 2, 0], 
     [0, 2, 0, 2], 
     [5, 0, 4, 2]]) 

In [112]: bincount_columns(x, minlength=7) 
Out[112]: 
array([[1, 0, 0, 1], 
     [0, 1, 0, 1], 
     [0, 3, 2, 0], 
     [0, 2, 0, 2], 
     [5, 0, 4, 2], 
     [0, 0, 0, 0], 
     [0, 0, 0, 0]]) 
関連する問題