Amostragem aleatória e saída do maior valor

1

Eu tenho um conjunto de dados bastante grande ~ 500 milhões de linhas. O conjunto de dados é semelhante abaixo. Col 1 é o número float, col 2 é mac id (id do dispositivo)

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

O problema requer a saída de ~ 100.000 amostras aleatórias após o agrupamento da col 2 e, em seguida, encontrar o maior valor da col 1 para esse grupo em particular.

A saída intermediária seria parecida com (group by 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

Depois disso, eu preciso do maior valor de cada grupo agrupado. A saída será semelhante a abaixo:

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

O passo final seria ter uma amostra verdadeiramente aleatória e a saída será semelhante a:

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

Qualquer ideia, como fazer isso. Acabei de começar a trabalhar no Linux e não tenho idéia de como realizar uma tarefa tão gigantesca. Qualquer ajuda seria apreciada.

    
por user4943236 15.07.2015 / 16:15

3 respostas

1

tente

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

onde

  • if ( $1 > V[$2]) V[$2]=$1 ; obter valor máximo para o mac
  • if ( before != $2 && before != "" ) { quando um novo valor mac chegar
  • r=rand()*100 ; if ( r > 50 ) printf "%s,%s\n",V[before],before ; calcula um valor aleatório e imprime se acima de 50% (você pode alterar para 5% ou 95%)
por 15.07.2015 / 16:47
0

Para registros. isso parece estar funcionando, nenhuma outra opção funcionou

sort -t "," -k2,2 -k1,1 -r output.txt| awk -F "," '!a[$2]++'|head -100
    
por 16.07.2015 / 07:28
0

500 milhões de linhas são muitos dados, por isso talvez você queira procurar uma forma mais escalonável de lidar com o trabalho. Dito isso, fazer isso com utilitários padrão do Linux é possível.

Supondo que seus dados estejam em um arquivo chamado data.txt , você pode imprimi-los no terminal usando 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

Esta saída pode então ser canalizada para sort com as opções -t ',' -k 2 . Essas opções dirão sort para dividir os dados usando uma vírgula como delimitador e, em seguida, classificar pelos valores na segunda coluna:

$ 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

Para sua próxima tarefa, você deverá usar sort com as opções -t ',' -k 1 -r . Isso classificará usando uma vírgula como o delimitador e o valor na primeira coluna. O -r classificará em ordem de revisão, fornecendo as maiores entradas primeiro:

$ 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

Você desejará enviar a saída do exemplo acima para sort novamente, desta vez usando as opções -t ',' -k 2 -u . Como antes, -t ',' e -k 2 dizem ao sort para usar a segunda coluna, enquanto a nova opção -u diz ao sort para manter apenas entradas únicas.

Como classificamos os dados pelos valores da primeira coluna, ao encontrar as entradas exclusivas, as mais altas serão encontradas primeiro. Isso nos dará o maior valor único para cada endereço 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

Finalmente, para obter uma amostra aleatória, você pode usar shuf com a opção -n 2 , em que dois é quantas amostras aleatórias você deseja:

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