私はデータの前処理、この場合は等幅のビニングを練習するための割り当てに取り組んでいますが、これらのnumpy関数に精通していないため、Pythonコードはちょっと醜いです:
def eq_width_bin(data, bins):
bin_edge = np.linspace(np.min(data), np.max(data), bins+1)
bin_edge[-1] += 1
re = []
for i in data:
for j in bin_edge:
if i < j:
re.append(int(np.argwhere(bin_edge==j))-1)
break
return re
data = np.array([80, 95, 70, 30, 20, 10, 75, 65, 98, 103, 130, 70])
print("After equal width binning:\n{}".format(eq_width_bin(data, 3)))
ただし、ルビーでは10行未満で実行できます(これは少し遅いという事実にもかかわらず):
def eq_width_bin(data, bins)
bin_edge = bins.times.collect{|i| data.min + (data.max - data.min) / bins * i} << data.max + 1
return data.collect{|i| bin_edge.index{|j| i < j} - 1}
end
data = [80, 95, 70, 30, 20, 10, 75, 65, 98, 103, 130, 70]
puts "After equal width binning:\n#{eq_width_bin(data, 3)}"
私はよく.select
.collect
.inject
.sort_by
rubyで配列を扱うことに慣れているので、上記のPythonコードを「美化」するために使用できるnumpy関数はありますか?(特に、numpyの組み込み関数がpyhtonで実行するよりもはるかに高速であることを知っています)
以下のように最初はこれが見えたbincount
かhistogram
が、出力は各値はフィットではなく、ビン当たりの項目数のビンです。
In [3]: eq_width_bin(data,3)
Out[3]: [1, 2, 1, 0, 0, 0, 1, 1, 2, 2, 2, 1]
あなたのゴミ箱:
In [10]: np.linspace(np.min(data),np.max(data),4)
Out[10]: array([ 10., 50., 90., 130.])
単純な整数除算で各値のビンを識別できます。
In [12]: (data-10)//40
Out[12]: array([1, 2, 1, 0, 0, 0, 1, 1, 2, 2, 3, 1])
そして、その3を次のように修正します。
In [16]: np.minimum((data-10)//40,2)
Out[16]: array([1, 2, 1, 0, 0, 0, 1, 1, 2, 2, 2, 1])
しかし、それはあなたの質問に答えません.select .collect .inject .sort_by
。手に負えない私はそれらに精通していません(私はSqueak
何年も前のファンでRuby
、少し手を出していましたが)。それらは、で収集されたものなど、イテレータのように聞こえますitertools
。
ではnumpy
、私たちは通常、反復的なアプローチを取ることはありません。むしろ、配列全体を調べて、除算や最小/最大などを実行します。
===
searchsorted
この問題でも機能します。
In [19]: np.searchsorted(Out[10],data)
Out[19]: array([2, 3, 2, 1, 1, 0, 2, 2, 3, 3, 3, 2])
In [21]: np.maximum(0,np.searchsorted(Out[10],data)-1)
Out[21]: array([1, 2, 1, 0, 0, 0, 1, 1, 2, 2, 2, 1])
Pythonループの(おそらく)よりクリーンな表現:
def foo(i, edges):
for j,n in enumerate(edges):
if i<n:
return j-1
return j-1
In [34]: edges = np.linspace(np.min(data),np.max(data),4).tolist()
In [35]: [foo(i,edges) for i in data]
Out[35]: [1, 2, 1, 0, 0, 0, 1, 1, 2, 2, 2, 1]
edges
リストに変換したのは、そのように繰り返す方が速いからです。
とitertools
:
In [55]: [len(list(itertools.takewhile(lambda x: x<i,edges)))-1 for i in data]
Out[55]: [1, 2, 1, 0, 0, -1, 1, 1, 2, 2, 2, 1]
===
別のアプローチ
In [45]: edges = np.linspace(np.min(data),np.max(data),4)
In [46]: data[:,None]<-edges
Out[46]:
array([[False, False, False, False],
[False, False, False, False],
[False, False, False, False],
[False, False, False, False],
[False, False, False, False],
[False, False, False, False],
[False, False, False, False],
[False, False, False, False],
[False, False, False, False],
[False, False, False, False],
[False, False, False, False],
[False, False, False, False]])
In [47]: np.argmax(data[:,None]<edges, axis=1)-1
Out[47]: array([ 1, 2, 1, 0, 0, 0, 1, 1, 2, 2, -1, 1])
それに-1
はクリーニングが必要です(Trueがない行)。
リストにはindex
メソッドがあります。これで、最後のRuby
行によく似た式を取得できます。リスト内包表記はRubyによく似ているようcollect
です。
In [88]: [[i<j for i in edges].index(False)-1 for j in data]
Out[88]: [1, 2, 1, 0, 0, -1, 1, 1, 2, 2, 2, 1]
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加