Anexar colunas em um arquivo de texto após a última linha

4

Uma versão menor de muitos arquivos de dados que eu tenho é assim:

0 0 0
0.05 9.6877884e-06 0.0024898597
0.1 4.2838688e-05 0.0049595502
0.15 0.00016929444 0.0074092494
0.2 0.00036426881 0.009839138
0.25 0.00055234582 0.012249394
0.3 0.00077448576 0.014640196
0.35 0.00082546537 0.017011717
0.4 0.0012371619 0.019364133
0.45 0.0013286382 0.02169761

Gostaria de terminar com algo como o seguinte, onde a primeira coluna é repetida e as entradas para a segunda coluna incluem as colunas 2 & acima do meu arquivo original.

0 0
0.05 9.6877884e-06
0.1 4.2838688e-05
0.15 0.00016929444
0.2 0.00036426881
0.25 0.00055234582
0.3 0.00077448576
0.35 0.00082546537
0.4 0.0012371619
0.45 0.0013286382
0 0
0.05 0.0024898597
0.1 0.0049595502
0.15 0.0074092494
0.2 0.009839138
0.25 0.012249394
0.3 0.014640196
0.35 0.017011717
0.4 0.019364133
0.45 0.021697611

Eu posso gerá-lo usando awk '{print $1 " " $2}' data > tmp seguido por awk '{print $1 " " $3}' data >> tmp , mas isso se torna muito tedioso para o número de colunas que eu tenho.

Existe uma maneira mais inteligente de alcançar o que eu preciso?

EDITAR

Eu gostaria de uma solução para um número arbitrário de colunas, n. A ordem correta de colunas para linhas é essencial para minhas necessidades. Assim, a coluna 3 da entrada deve ser "movida" para baixo da coluna 2 de entrada, coluna 4 abaixo de 2 e 3, etc., sendo a coluna 1 empilhada por baixo repetidamente. A primeira coluna deve estar em ordem numérica crescente para quantas linhas cada coluna tiver, por exemplo, 0, 0,05, ..., 0,45, 0, 0,05, ..., 0,45, 0,0,05, ..., 0,45, etc. / p>     

por nstjhp 14.04.2014 / 16:44

3 respostas

2

Awk

este script awk funcionará em um número arbitrário de colunas > 2 e ordem de aparição será preservada como horizontal, sem nenhuma suposição feita sobre o que as colunas são ( ie não importa se elas são numéricas ou não, ordenadas ou não, etc):

{
    for (i = 2; i <= NF; i++) {
        a[j + i] = $1 " " $i
    }
    j += (i - 1);
}
END {
    OutNR = NR * NF;
    for (i = 2; i <= NF; i++) {
        for (j = 0; j < OutNR; j += NF) { 
            print a[j + i];
        }
    }
}

Dado:

0 0 0 0.2340
0.05 9.6877884e-06 0.0024898597 0.2341
0.1 4.2838688e-05 0.0049595502 0.2342
0.15 0.00016929444 0.0074092494 0.2343
0.2 0.00036426881 0.009839138 0.2344
0.25 0.00055234582 0.012249394 0.2345
0.3 0.00077448576 0.014640196 0.2346
0.35 0.00082546537 0.017011717 0.2347
0.4 0.0012371619 0.019364133 0.2348
0.45 0.0013286382 0.02169761 0.2349

Ordenar por coluna (2 .. n ) e depois por linha:

0 0
0.05 9.6877884e-06
0.1 4.2838688e-05
0.15 0.00016929444
0.2 0.00036426881
0.25 0.00055234582
0.3 0.00077448576
0.35 0.00082546537
0.4 0.0012371619
0.45 0.0013286382
0 0
0.05 0.0024898597
0.1 0.0049595502
0.15 0.0074092494
0.2 0.009839138
0.25 0.012249394
0.3 0.014640196
0.35 0.017011717
0.4 0.019364133
0.45 0.02169761
0 0.2340
0.05 0.2341
0.1 0.2342
0.15 0.2343
0.2 0.2344
0.25 0.2345
0.3 0.2346
0.35 0.2347
0.4 0.2348
0.45 0.2349

R

Embora a maioria das pessoas não pense em R para processamento de texto, neste caso, é realmente um pouco mais direto, embora toda a configuração da opção pareça mais complexa do que realmente é. A essência desta solução é simplesmente rbind() multiple cbind() :

d.in <- read.table(file = commandArgs(trailingOnly = T)[1]
                    , colClasses = "character");
d.out<-data.frame();
for (i in 2:length(d.in)) {
    d.out <- rbind(d.out, cbind(d.in[,1], d.in[,i]));
}
write.table(d.out, row.names = F, col.names = F, quote = F);

Então, apenas:

$ Rscript script.R data.txt
0 0
0.05 9.6877884e-06
0.1 4.2838688e-05
0.15 0.00016929444
0.2 0.00036426881
0.25 0.00055234582
0.3 0.00077448576
0.35 0.00082546537
0.4 0.0012371619
0.45 0.0013286382
0 0
0.05 0.0024898597
0.1 0.0049595502
0.15 0.0074092494
0.2 0.009839138
0.25 0.012249394
0.3 0.014640196
0.35 0.017011717
0.4 0.019364133
0.45 0.02169761
0 0.2340
0.05 0.2341
0.1 0.2342
0.15 0.2343
0.2 0.2344
0.25 0.2345
0.3 0.2346
0.35 0.2347
0.4 0.2348
0.45 0.2349
    
por 14.04.2014 / 17:12
0

Se a ordem não importa, você pode simplesmente usar isto:

awk '{for(i=2;i<=NF;i++)print $1,$i}' file
    
por 14.04.2014 / 17:31
0

Aqui está uma solução awk :

$ awk '{a[i++]=$1" "$3;print $1,$2}END{for(i=0;i<length(a);i++){print a[i]}}' file
0 0
0.05 9.6877884e-06
0.1 4.2838688e-05
0.15 0.00016929444
0.2 0.00036426881
0.25 0.00055234582
0.3 0.00077448576
0.35 0.00082546537
0.4 0.0012371619
0.45 0.0013286382
0 0
0.05 0.0024898597
0.1 0.0049595502
0.15 0.0074092494
0.2 0.009839138
0.25 0.012249394
0.3 0.014640196
0.35 0.017011717
0.4 0.019364133
0.45 0.02169761

Explicação

  • Ao processar o arquivo, salvamos $ 1 e $ 3 na matriz a com índice de 0 para o número de linhas com cada linha. Em seguida, imprima $1 e $2 .

  • No final, passamos pelo array a , imprimimos cada um de seus elementos (que é o valor $1 $3 ). A ordem é mantida porque fazemos um loop com o índice de 0 ao comprimento da matriz a novamente.

Atualizado

Para colunas arbitrárias n, eu uso perl :

$ perl -anle '$h{$i++} = [@F[0..$#F]];
  END {
      for $j (1..$#F) {
          for (sort {$a<=>$b} keys %h) {
              print $h{$_}->[0]," ",$h{$_}->[$j]
          }
      }
  }' file
    
por 14.04.2014 / 16:57