6

「a」という名前の100000000x2配列があり、最初の列にインデックスがあり、2番目の列に関連する値があります。各インデックスの2番目の列の数値の中央値を取得する必要があります。これは私がforステートメントでそれを行う方法です:

import numpy as np
b = np.zeros(1000000)
a = np.array([[1, 2],
              [1, 3],
              [2, 3],
              [2, 4],
              [2, 6],
              [1, 4],
              ...
              ...
              [1000000,6]])
for i in xrange(1000000):
    b[i]=np.median(a[np.where(a[:,0]==i),1])

明らかに、反復では遅すぎます:何か提案はありますか?ありがとう

4

5 に答える 5

6

これは「groupby」操作として知られています。Pandas(http://pandas.pydata.org/)は、このための優れたツールです。

import numpy as np
import pandas as pd

a = np.array([[1.0, 2.0],
              [1.0, 3.0],
              [2.0, 5.0],
              [2.0, 6.0],
              [2.0, 8.0],
              [1.0, 4.0],
              [1.0, 1.0],
              [1.0, 3.5],
              [5.0, 8.0],
              [2.0, 1.0],
              [5.0, 9.0]])

# Create the pandas DataFrame.
df = pd.DataFrame(a, columns=['index', 'value'])

# Form the groups.
grouped = df.groupby('index')

# `result` is the DataFrame containing the aggregated results.
result = grouped.aggregate(np.median)
print result

出力:

       value
index       
1        3.0
2        5.5
5        8.5

元のデータを直接含むDataFrameを作成する方法はいくつかあるため、必ずしもa最初にnumpy配列を作成する必要はありません。

パンダでのgroupby操作の詳細:http://pandas.pydata.org/pandas-docs/dev/groupby.html

于 2012-09-25T21:06:11.697 に答える
4

これを行うのは少し面倒ですが、少なくとも==、並べ替えを使用して、面倒なことを簡単に取り除くことができます(そしてそれはおそらくあなたのスピードキラーです)。もっと試してみるのはおそらくあまり役​​に立ちませんが、自分で並べ替えれば可能かもしれません。

# First sor the whole thing (probably other ways):
sorter = np.argsort(a[:,0]) # sort by class.
a = a[sorter] # sorted version of a

# Now we need to find where there are changes in the class:
w = np.where(a[:-1,0] != a[1:,0])[0] + 1 # Where the class changes.
# for simplicity, append [0] and [len(a)] to have full slices...
w = np.concatenate([0], w, [len(a)])
result = np.zeros(len(w)-1, dtype=a.dtype)
for i in xrange(0, len(w)-1):
    result[0] = np.median(a[w[i]:w[i+1]])

# If the classes are not exactly 1, 2, ..., N we could add class information:
classes = a[w[:-1],0]

すべてのクラスが同じサイズである場合、2などとまったく同じ数の1があります。ただし、より良い方法があります。

編集:最後のforループも回避するための解決策について、Bitwisesバージョンを確認してください(np.unique速度はとにかく重要ではないので、彼はあなたが好むかもしれないこのコードのいくつかも隠します)。

于 2012-09-25T20:43:41.893 に答える
3

これが私のバージョンです。追加モジュールはありません。配列を一度ソートすると、次の最初の列のインデックスを数えるだけで、中央値のインデックスを簡単に取得できます。

# sort by first column and then by second
b=a[np.lexsort((a[:,1],a[:,0]))]

# find central value for each index
c=np.unique(b[:,0],return_index=True)[1]
d=np.r_[c,len(a)]
inds=(d[1:]+d[:-1]-1)/2.0
# final result (as suggested by seberg)
medians=np.mean(np.c_[b[np.floor(inds).astype(int),1],
                      b[np.ceil(inds).astype(int),1]],1)

# inds is the index of the median value for each key

必要に応じて、コードを短くすることができます。

于 2012-09-25T21:24:51.420 に答える
2

これをたくさんやりたいと思ったら、パンダライブラリを見てみることをお勧めします。これにより、これはパイと同じくらい簡単になります。

>>> df = pandas.DataFrame([["A", 1], ["B", 2], ["A", 3], ["A", 4], ["B", 5]], columns=["One", "Two"])
>>> print df
  One  Two
0   A    1
1   B    2
2   A    3
3   A    4
4   B    5
>>> df.groupby('One').median()
      Two
One     
A    3.0
B    3.5
于 2012-09-25T21:07:20.907 に答える
1

簡単な1行のアプローチ:

result = [np.median(a[a[:,0]==ii,1]) for ii in np.unique(a[:,0])]

精度を犠牲にすることなくそれをより速くするためにあなたができることがたくさんあると私は確信していません。ただし、別の試みがあります。ソート手順をスキップできる場合は、より高速になる可能性があります。

num_in_ind = np.bincount(a[:,0])
results = [np.sort(a[a[:,0]==ii,1])[num_in_ind[ii]/2] for ii in np.unique(a[:,0])]

後者は、小さなアレイの場合は非常にわずかに高速です。それが十分に速いかどうかわからない。

于 2012-09-25T21:10:39.420 に答える