Como pesquisar os valores de um valor de índice de um arquivo big data?

0

Eu tenho um arquivo de dados (data_array.txt no exemplo) e um arquivo de índice, index.txt, no qual eu quero extrair os dados do arquivo de dados que tem o mesmo ID no arquivo de índice e armazenar em um arquivo novo arquivo, Out.txt. Eu também quero colocar NA, no Out.txt, para aqueles IDs que não têm valor no arquivo de dados. Eu sei como fazer isso por uma coluna. Mas meus dados têm mais de 1000 colunas (de 1 a 1344). Eu quero que você me ajude com um script que pode fazer isso mais rápido. Meu arquivo de dados, id do índice e propuseram colocar da seguinte forma.

data_array.txt

Id  1   2   3   .   .   1344
1   10  20  30  .   .   -1
2   20  30  40  .   .   -2
3   30  40  50  .   .   -3
4   40  50  60  .   .   -4
6   60  60  70  .   .   -5
8   80  70  80  .   .   -6
10  100 80  90  .   .   -7

index.txt

Id
1
2
8
9
10

Saída exigida é

Out.txt

Id  1   2   3   .   .   1344
1   10  20  30  .   .   -1
2   20  30  40  .   .   -2
8   80  70  80  .   .   -6
9   NA  NA  NA          NA
10  100 80  90  .   .   -7
    
por AiB 02.01.2014 / 13:40

2 respostas

2

Aqui está um pequeno script awk que eu criei, que deve procurar linhas que correspondam aos seus índices. Basta colocá-lo em um arquivo (por exemplo, lookup.awk) e executar da seguinte forma:

lookup.awk

BEGIN {
        # read lookup variables from the commandline and put them in an array
        split(indexes, index_array, " ");
}

NR=1 {
        # set the number of columns to the amount that's on the first line (only used for NA printing)
        nr_of_fields = NF-1;
}

# For every line in your data file do the following
{
        # check if the first field matches a value in the index array
        for (var in index_array) {
                if ($1 == index_array[var]) {
                        # when a match is found print the line and remove the value from the index array
                        print $0;
                        delete index_array[var];
                        next;
                }
        }
}

END {
        # after all matching lines are found, print "NA" lines for the indexes that are still in the array
        for (var in index_array) {
                printf index_array[var];
                for (i=1; i<nr_of_fields; i++) {
                        printf "  NA";
                }
                printf "\n";
        }
}

Você pode executá-lo assim:

$ awk -f ./lookup.awk -v indexes="1 2 3 4 5 6 7 8 9 10" data.txt | sort -n
1   10  20  30  .   .   -1
2   20  30  40  .   .   -2
3   30  40  50  .   .   -3
4   40  50  60  .   .   -4
5  NA  NA  NA  NA  NA
6   60  60  70  .   .   -5
7  NA  NA  NA  NA  NA
8   80  70  80  .   .   -6
9  NA  NA  NA  NA  NA
10  100 80  90  .   .   -7

Por favor, note que este script awk não produz os valores em alguma ordem como seu índice (que requer alguma lógica extra).

    
por 02.01.2014 / 14:58
1

Não tenho certeza se entendi, parece que você quer que a saída seja exatamente igual à entrada com uma linha adicionada contendo NAs para qualquer índice não presente no arquivo de entrada. Em caso afirmativo, isso deve funcionar:

$ awk '{
  if(NR==1){fields=NF;}
  if(NR==FNR){i[$1]=$0;}
  else{
    if($1 in i){print i[$1]}
    else{
      printf "%s%s", $1,OFS; 
      for(k=1;k<fields;k++){printf "%s%s","NA",OFS}
      print ""
    }  
  } 
}' data index 
Id  1   2   3   .   .   1344
1   10  20  30  .   .   -1
2   20  30  40  .   .   -2
3   30  40  50  .   .   -3
4   40  50  60  .   .   -4
5 NA NA NA NA NA NA 
6   60  60  70  .   .   -5
7 NA NA NA NA NA NA 
8   80  70  80  .   .   -6
9 NA NA NA NA NA NA 
10  100 80  90  .   .   -7

Pessoalmente, eu faria isso em Perl:

$ cat data index | perl -ne '@a=split(/\s+/); 
   if($#a>1){$id{$a[0]}=$_; $na||="NA "x$#a . "\n";}
   else{$f=$id{$a[0]}||"$a[0] $na"; print "$f"}'
Id  1   2   3   .   .   1344
1   10  20  30  .   .   -1
2   20  30  40  .   .   -2
3   30  40  50  .   .   -3
4   40  50  60  .   .   -4
5 NA NA NA NA NA NA 
6   60  60  70  .   .   -5
7 NA NA NA NA NA NA 
8   80  70  80  .   .   -6
9 NA NA NA NA NA NA 
10  100 80  90  .   .   -7
    
por 02.01.2014 / 15:00