最大値をランダムにサンプリングして出力します。

最大値をランダムにサンプリングして出力します。

私はかなり大きなデータセット〜5億行を持っています。データセットは以下の通りです。列1は浮動小数点数、列2はmac id(デバイスID)です。

1616.93,ac:22:0b:a6:22:c3
2872.32,c0:bd:d1:36:bb:49
3314.55,d4:0b:1a:39:19:b2
2854.11,18:f6:43:64:81:67
3540.68,18:f6:43:64:81:67
3856.91,ac:22:0b:a6:22:c3
2497.93,d4:0b:1a:39:19:b2

この問題は、列2をグループ化してから約100,000個のランダムサンプルを出力し、その特定のグループの列1で最大値を見つけることが必要です。

中間出力は次のとおりです(col1でグループ化)。

1616.93,ac:22:0b:a6:22:c3
3856.91,ac:22:0b:a6:22:c3
2854.11,18:f6:43:64:81:67
3540.68,18:f6:43:64:81:67
2872.32,c0:bd:d1:36:bb:49
3314.55,d4:0b:1a:39:19:b2
2497.93,d4:0b:1a:39:19:b2

その後、グループ化された各列の最大値が必要です。出力は次のとおりです。

3856.91,ac:22:0b:a6:22:c3
3540.68,18:f6:43:64:81:67
2872.32,c0:bd:d1:36:bb:49
3314.55,d4:0b:1a:39:19:b2

最後のステップは本当にランダムなサンプルを得ることです。出力は次のとおりです。

3540.68,18:f6:43:64:81:67
2872.32,c0:bd:d1:36:bb:49

これを行う方法についてのアイデアがあります。私はちょうどLinuxを使い始めましたが、これは難しいことをする方法がわかりません。どんな助けでも大変感謝します。

答え1

努力する

BEGIN { srand() ;r=0 ; FS="," ; before="" ; }
{ if ( $1 > V[$2]) V[$2]=$1 ;
    if ( before != $2 && before != ""  ) {
          r=rand()*100 ;
       if ( r  > 50 ) printf "%s,%s\n",V[before],before ;
        }
 before=$2 ;
 }  data-file.txt

どこ

  • if ( $1 > V[$2]) V[$2]=$1; macの最大値を取得します。
  • if ( before != $2 && before != "" ) {新しいmac値が表示されたとき
  • r=rand()*100 ; if ( r > 50 ) printf "%s,%s\n",V[before],before ;任意の値を計算して50%を超えると印刷します。 (5%、95%に変更可能)

答え2

5億行は大量のデータなので、これを処理するためのよりスケーラブルな方法を探したいかもしれません。つまり、標準のLinuxユーティリティを使用してこれを行うことができます。

データが名前付きファイルにあると仮定すると、data.txt 以下を使用して端末に印刷できますcat

$ cat data.txt
1616.93,ac:22:0b:a6:22:c3
2872.32,c0:bd:d1:36:bb:49
3314.55,d4:0b:1a:39:19:b2
2854.11,18:f6:43:64:81:67
3540.68,18:f6:43:64:81:67
3856.91,ac:22:0b:a6:22:c3
2497.93,d4:0b:1a:39:19:b2

sortその後、optionsを使用してこの出力をパイプに接続できます-t ',' -k 2。これらのオプションは、sortカンマを区切り文字として使用してデータを分割し、2番目の列の値に基づいてソートするように指示します。

$ cat data.txt | sort -t ',' -k 2
2854.11,18:f6:43:64:81:67
3540.68,18:f6:43:64:81:67
1616.93,ac:22:0b:a6:22:c3
3856.91,ac:22:0b:a6:22:c3
2872.32,c0:bd:d1:36:bb:49
2497.93,d4:0b:1a:39:19:b2
3314.55,d4:0b:1a:39:19:b2

sort次のミッションではオプションを使用する必要があります-t ',' -k 1 -r。これにより、カンマを区切り文字として使用し、最初の列の値を使用してソートされます。-r最大の項目を最初に提供し、適切な順序で並べ替えます。

$ cat data.txt | sort -t ',' -k 1 -r
3856.91,ac:22:0b:a6:22:c3
3540.68,18:f6:43:64:81:67
3314.55,d4:0b:1a:39:19:b2
2872.32,c0:bd:d1:36:bb:49
2854.11,18:f6:43:64:81:67
2497.93,d4:0b:1a:39:19:b2
1616.93,ac:22:0b:a6:22:c3

sort次に、このオプションを使用して、上記の例の出力をパイプに再接続する必要があります-t ',' -k 2 -u。以前と同様に、sortは2番目の列を使用するように指示しますが、新しいオプションはsortに固有の項目のみを保持するように指示し-t ','ます。-k 2-u

最初の列の値に基づいてデータをソートしたため、一意の項目を見つけると、最も高い項目が最初に検索されます。これにより、各 MAC アドレスに対して最高の単一値が提供されます。

$ cat data.txt | sort -t ',' -k 1 -r | sort -t ',' -k 2 -u
3540.68,18:f6:43:64:81:67
3856.91,ac:22:0b:a6:22:c3
2872.32,c0:bd:d1:36:bb:49
3314.55,d4:0b:1a:39:19:b2

最後に、ランダムサンプルを取得するには、shuf次のオプションを使用できます-n 2。ここで、2 は所望のランダムなサンプル数です。

$ shuf data.txt -n 2
3856.91,ac:22:0b:a6:22:c3
3314.55,d4:0b:1a:39:19:b2

答え3

記録用。これはうまくいくようです。他のオプションは機能しません。

sort -t "," -k2,2 -k1,1 -r output.txt| awk -F "," '!a[$2]++'|head -100

関連情報