36

したがって、それぞれ 100 要素を持つ 100,000 個の float 配列があるとします。X 個の値の最大数が必要ですが、Y より大きい場合のみです。これに一致しない要素はすべて 0 に設定する必要があります。Python でこれを行う最速の方法は何ですか? 秩序を維持する必要があります。ほとんどの要素はすでに 0 に設定されています。

サンプル変数:

array = [.06, .25, 0, .15, .5, 0, 0, 0.04, 0, 0]
highCountX = 3
lowValY = .1

期待される結果:

array = [0, .25, 0, .15, .5, 0, 0, 0, 0, 0]
4

9 に答える 9

78

これはNumPyの典型的な仕事であり、これらの種類の操作では非常に高速です。

array_np = numpy.asarray(array)
low_values_flags = array_np < lowValY  # Where values are low
array_np[low_values_flags] = 0  # All low values set to 0

これで、highCountXの最大の要素のみが必要な場合は、(0に設定して並べ替える代わりに)小さな要素を「忘れて」、大きな要素のリストのみを並べ替えることもできます。

array_np = numpy.asarray(array)
print numpy.sort(array_np[array_np >= lowValY])[-highCountX:]

もちろん、必要な要素が少ない場合は、配列全体を並べ替えるのは最適ではない可能性があります。ニーズに応じて、標準のheapqモジュールを検討することをお勧めします。

于 2009-10-26T09:49:08.640 に答える
7

NumPy には、まさにそれを行う特別な MaskedArray クラスがあります。任意の前提条件に基づいて要素を「マスク」できます。これは、ゼロを割り当てるよりもニーズをより適切に表しています。適切な場合、numpy 操作はマスクされた値を無視します (たとえば、平均値の検索)。

>>> from numpy import ma
>>> x = ma.array([.06, .25, 0, .15, .5, 0, 0, 0.04, 0, 0])
>>> x1 = ma.masked_inside(0, 0.1) # mask everything in 0..0.1 range
>>> x1
masked_array(data = [-- 0.25 -- 0.15 0.5 -- -- -- -- --],
         mask = [ True False True False False True True True True True],
   fill_value = 1e+20)
>>> print x.filled(0) # Fill with zeroes
[ 0 0.25 0 0.15 0.5 0 0 0 0 0 ]

追加の利点として、マスクされた配列は、必要に応じて matplotlib 視覚化ライブラリで十分にサポートされています。

numpy のマスクされた配列に関するドキュメント

于 2009-10-26T11:05:35.820 に答える
6

使用numpy

# assign zero to all elements less than or equal to `lowValY`
a[a<=lowValY] = 0 
# find n-th largest element in the array (where n=highCountX)
x = partial_sort(a, highCountX, reverse=True)[:highCountX][-1]
# 
a[a<x] = 0 #NOTE: it might leave more than highCountX non-zero elements
           # . if there are duplicates

どこpartial_sortにある可能性があります:

def partial_sort(a, n, reverse=False):
    #NOTE: in general it should return full list but in your case this will do
    return sorted(a, reverse=reverse)[:n] 

式は次のようa[a<value] = 0に記述できnumpyます。

for i, x in enumerate(a):
    if x < value:
       a[i] = 0
于 2009-10-26T09:52:46.697 に答える
5

最も簡単な方法は次のとおりです。

topX = sorted([x for x in array if x > lowValY], reverse=True)[highCountX-1]
print [x if x >= topX else 0 for x in array]

断片的に、これは より大きいすべての要素を選択しますlowValY:

[x for x in array if x > lowValY]

この配列には、しきい値を超える要素数のみが含まれます。次に、最大値が先頭になるように並べ替えます。

sorted(..., reverse=True)

次に、リスト インデックスが上位highCountX要素のしきい値を取得します。

sorted(...)[highCountX-1]

最後に、元の配列は別のリスト内包表記を使用して埋められます。

[x if x >= topX else 0 for x in array]

(あなたの例では)3番目に高い要素である2つ以上の等しい要素がある境界条件があります。結果の配列には、その要素が複数回含まれます。

if など、他の境界条件もありますlen(array) < highCountX。このような条件の処理は、実装者に任されています。

于 2009-10-26T09:29:35.143 に答える
2

しきい値をゼロに下回る設定要素は簡単です。

array = [ x if x > threshold else 0.0 for x in array ]

(さらに、必要に応じてabs()を使用することもあります。)

ただし、N個の最大数の要件は少しあいまいです。たとえば、しきい値を超えるN + 1の等しい数がある場合はどうなりますか?どちらを切り捨てますか?

最初に配列を並べ替えてから、しきい値をN番目の要素の値に設定できます。

threshold = sorted(array, reverse=True)[N]
array = [ x if x >= threshold else 0.0 for x in array ]

注:このソリューションは、パフォーマンスではなく読みやすさを重視して最適化されています。

于 2009-10-26T09:51:39.763 に答える
1

マップとラムダを使用できます。十分に高速である必要があります。

new_array = map(lambda x: x if x>y else 0, array)
于 2009-10-26T09:56:40.440 に答える
0

エゴンが言うように、ヒープを使用することは良い考えです。ただし、heapq.nlargest関数を使用して労力を削減できます。

import heapq 

array =  [.06, .25, 0, .15, .5, 0, 0, 0.04, 0, 0]
highCountX = 3
lowValY = .1

threshold = max(heapq.nlargest(highCountX, array)[-1], lowValY)
array = [x if x >= threshold else 0 for x in array]
于 2009-10-27T04:32:19.673 に答える
0

ヒープを使用します。

これは時間内に機能しO(n*lg(HighCountX))ます。

import heapq

heap = []
array =  [.06, .25, 0, .15, .5, 0, 0, 0.04, 0, 0]
highCountX = 3
lowValY = .1

for i in range(1,highCountX):
    heappush(heap, lowValY)
    heappop(heap)

for i in range( 0, len(array) - 1)
    if array[i] > heap[0]:
        heappush(heap, array[i])

min = heap[0]

array = [x if x >= min else 0 for x in array]

deletemin は、ヒープO(lg(k))と挿入でO(lg(k))、またはO(1)使用するヒープの種類に応じて機能します。

于 2009-10-26T10:33:18.373 に答える