2016-11-28 5 views
1

私は1000のグループ内の整数データポイントの数を数えようとしています。データポイントのカウント/グループ化:for-loopまたはlist comprehension?

我々は範囲0..999999 10,000データ・ポイントを持っていると仮定しましょう:バリアントはそれぞれ1000の範囲内のデータポイントのカウント数を含むリストを生成するために、「より良い」の方法でしょう

import random 
random.seed(123456) # generate a reproducable sequence 

# make 10000 numbers in range 0..99999 
maxn = 99999 
numbers = [random.randint(0,maxn) for i in range(10000)] 

今グループ?

"ベター"(詳しく説明してください)次のいずれかを意味することができます:6ヶ月後

  • 良く読める
  • よりニシキヘビ

    • 良いパフォーマンス...

    バリアント1:

    # generate a zero-initialized "array" to hold the counts per 1000's block 
    blocks1 = [0 for i in range(maxn/1000 +1)] # init 1D "array" 
    
    for num in numbers: 
        blocks1[num/1000] += 1 # int divide by 1000 gives index 
    
    print blocks1[1] # show how many in range 1000..1999 
    

    バリアント2:Pythonでより良いものをやって私を助けるため

    # Use a really wild list comprehension: 
    blocks2 = [len(filter(lambda num: num/1000 == i, numbers)) 
        for i in range(maxn/1000+1)] 
    
    print blocks2[1] # show how many in range 1000..1999 
    

    ありがとう! :-)

  • 答えて

    2

    あなたが物事を数えようとしている場合、最も平凡な答えはCounterです。タイプはdictです。キーはそれぞれ "バンド" や、グループ内の数千人の数がある

    Counter({0: 87, 
         1: 113, 
         2: 117, 
         3: 99, 
         4: 114, 
         ... 
    

    :ようなもので

    from collections import Counter 
    
    Counter(n // 1000 for n in numbers) 
    

    結果。したがって、キー0は0〜999の値を記録し、1は1000〜1999の値を記録します。

    しかし、これももっときれいに行うことができます。まず、値をバンド名にマップする関数(この場合は1行のラムダ関数)を定義します。むしろ、直接それが表す範囲を明記

    Counter({'0-999': 87, 
         '1000-1999': 113, 
         '10000-10999': 102, 
         '11000-11999': 114, 
         '12000-12999': 113, 
         ... 
    

    キーの順序が異なっており、キーは、より多くの象徴です:

    bandof = lambda x, b=1000: '{}-{}'.format(x//b*b, (x//b+1)*b-1) 
    Counter(bandof(n) for n in numbers) 
    

    のようなものが得られます。そして、一般ジェネレータ式渡っCounterを構築あなたの頭の中の値の範囲にインデックスを変換するよりも、

    このように一般化すると、バンドサイズを変更する必要があるときはいつでも、それは簡単です。例えば。

    Counter(bandof(n, 2000) for n in numbers) 
    

    収量:

    Counter({'0-1999': 200, 
         '10000-11999': 216, 
         '12000-13999': 235, 
         '14000-15999': 186, 
         '16000-17999': 188, 
         ... 
    

    ピックバンドサイズ100、250、500、1000年、5000、またはものは何でも好きなバンドサイズ2000。素敵な丸数字に制限されていません。あなたが391のバンドサイズを望むなら、それはあまりにも機能します。

    最後のトリック:文字列キーは印刷目的では魅力的ですが、ソートや他の種類の処理にはあまり便利ではありません。

    bandtuple = lambda x, b=1000: (x//b*b, (x//b+1)*b-1) 
    

    あなたが以前のように、このカテゴライザー関数を呼び出しますので、代わりに文字列にグループ名をフォーマットする、それがtupleを使用すると便利です。のは、野生と狂気を取得してみましょうと珍しいバンドサイズでそれを行う:

    Counter(bandtuple(n, 3924) for n in numbers) 
    

    のようなものが得られますバンドが起動し、値がまだはっきりしている停止今

    Counter({(0, 3923): 411, 
         (3924, 7847): 386, 
         (7848, 11771): 403, 
         (11772, 15695): 417, 
         (15696, 19619): 396, 
         ... 
    

    を、彼らはすぐにもしていますデータとしても使用できます。

    :ここで示されるバンドの開始値と終了値は、包括的/閉鎖的な間隔です。これは多くの用途に適していますが、Pythonのrange()ファンクション/ジェネレータで一般的に返される半オープン範囲とは少し異なりますが、それほど重大ではありません。

    +0

    'collections'と' Counter'のヒントに感謝します。私はこれがチェックアウトする価値のあるモジュールだと思います。私は、あなたの提案されたルートを 'Counter'を使って追跡し、タプルと値のペアを返すようにします。あなたの時間と大きな説明に感謝します!回答が受け入れられました:-) – Moonbase

    関連する問題