2011-12-16 16 views
3

関数の一部として、入力ベクトル/行列の各列の平均値を含むベクトル/行列(入力に応じて)を生成するコードを記述しています。バツ'。これらの値は、入力ベクトルと同じ形状のベクトル/行列に格納されます。ベクトルと行列を扱う関数を書くには

それは1-Dおよびマトリックスアレイの両方で動作させるために私の予備的な解決策は非常にある厄介な(!):

MATLABの背景から来る
# 'x' is of type array and can be a vector or matrix. 
import scipy as sp 
shp = sp.shape(x) 
x_mean = sp.array(sp.zeros(sp.shape(x))) 

try: # if input is a matrix 
    shp_range = range(shp[1]) 
    for d in shp_range: 
     x_mean[:,d] = sp.mean(x[:,d])*sp.ones(sp.shape(z)) 
except IndexError: # error occurs if the input is a vector 
    z = sp.zeros((shp[0],)) 
    x_mean = sp.mean(x)*sp.ones(sp.shape(z))  

、これはMATLABでどのように見えるかです:

[R,C] = size(x); 
for d = 1:C, 
    xmean(:,d) = zeros(R,1) + mean(x(:,d)); 
end 

これは、誤差のないベクトルと行列の両方で機能します。

私の質問は、(醜い)try/exceptブロックを使わずにベクトルと行列の両方の入力にPythonコードを作用させるにはどうすればいいですか?

ありがとうございます!

+0

可能デュープ: http://stackoverflow.com/q/8287047/48837 –

+1

公正であるために、matlabには1D配列はありませんl。 matlab _is_ 2Dの "1D"ベクトル。 –

+0

2D/1D出力をノルムの計算のようなものに使うつもりならば、2D出力は必要なく、あらゆる場合に1Dアレイを放送で取り除くことができます。 – cyborg

答えて

3

最初numpyでの放送についての簡単なメモ。私がmatlabからPythonに切り替えたとき、ブロードキャストはちょっと混乱していましたが、それを理解する時間があれば、それがどれほど有用であるかを理解しました。放送についての詳細はhttp://docs.scipy.org/doc/numpy/user/basics.broadcasting.html

numpyの(m、)配列をブロードキャストしているため(ベクトルと呼んでいる)、(1、m)配列または(1、m)配列と本質的に等価です。 1、m)の配列などである。 (m、)配列を(m、1)配列のように動作させたいと思うようです。私はこれが時々、特にlinalgモジュールで起こると信じていますが、もしあなたがそれをやろうとするならば、あなたは数の少ない規則を破っていることを知るべきです。

その警告コードがあります:

import scipy as sp 
def my_mean(x): 
    if x.ndim == 1: 
     x = x[:, sp.newaxis] 
    m = sp.empty(x.shape) 
    m[:] = x.mean(0) 
    return sp.squeeze(m) 

と例:

In [6]: x = sp.arange(30).reshape(5,6) 

In [7]: x 
Out[7]: 
array([[ 0, 1, 2, 3, 4, 5], 
     [ 6, 7, 8, 9, 10, 11], 
     [12, 13, 14, 15, 16, 17], 
     [18, 19, 20, 21, 22, 23], 
     [24, 25, 26, 27, 28, 29]]) 

In [8]: my_mean(x) 
Out[8]: 
array([[ 12., 13., 14., 15., 16., 17.], 
     [ 12., 13., 14., 15., 16., 17.], 
     [ 12., 13., 14., 15., 16., 17.], 
     [ 12., 13., 14., 15., 16., 17.], 
     [ 12., 13., 14., 15., 16., 17.]]) 

In [9]: my_mean(x[0]) 
Out[9]: array([ 2.5, 2.5, 2.5, 2.5, 2.5, 2.5]) 

これはtileを使用するよりも高速ですが、タイミングが怒鳴るです:

In [1]: import scipy as sp 

In [2]: x = sp.arange(30).reshape(5,6) 

In [3]: m = x.mean(0) 

In [5]: timeit m_2d = sp.empty(x.shape); m_2d[:] = m 
100000 loops, best of 3: 2.58 us per loop 

In [6]: timeit m_2d = sp.tile(m, (len(x), 1)) 
100000 loops, best of 3: 13.3 us per loop 
+0

非常に明確な答えをありがとう - 私の多くを助けた! – rapidfyre

6

axisパラメータを使用すると、Numpyはベクトル(ベクトルの場合)または列(行列の場合)に沿って計算を実行します。平均計算自体のためにベクトルと行列を区別する必要はありません。それは巨大な行列に対して少し遅いかもしれませんが、その後、出力を構築するために、あなたは、昔ながらのリストの内包表記を使用することができます。それは割り当てなければならないので、リスト内包で出力を作成

import numpy as np 
m = np.mean(x,axis=0) # For vector x, calculate the mean. For matrix x, calculate the means of the columns 
x_mean = np.array([m for k in x]) # replace elements for vectors or rows for matrices 

が遅いですメモリは2回、リストの場合は1回、アレイの場合は1回です。 np.repeatまたはnp.tileを使用するとベクトル入力の方が面白くなりますが、出力は各行に1つの長さのベクトルを持つ入れ子行列になります。速度が優雅以上に重要場合は、この場合に、最後の行を置き換えることができます:ところで

if len(x.shape) == 1: 
    x_mean = m*np.ones(len(x)) 
else: 
    x_mean = np.tile(m, (x.shape[1],1)) 

、MATLABコードは、行ベクトルと列ベクトル(xx'でそれを実行してみてください)のために動作が異なります。

+0

良い点。私は急いでいて、物事を説明するのにもっと時間がかかるはずでした。あなたの答えはそれを説明する非常に良い仕事です。 (私とは違って、実際に正しいと同様に):) –

+0

@JoeKington - ありがとう!私は速度のためのあなたの元の答えに基づいて代替を追加しました。 – mtrw

+0

MATLABコードの違いについて申し訳ありません - 私は列ベクトルのポイントを説明しようとしていました(私のプログラムでは行ベクタは期待していません)。しかし、明確化のおかげで! – rapidfyre