Mover arquivo / tabela pela média de uma coluna

2

Eu tenho o seguinte programa que me permite mover um arquivo (na verdade, uma tabela) se o valor da primeira linha da quarta coluna for o mais alto (em comparação com outros 8 arquivos com o mesmo estilo de nomenclatura. o script:

#! /bin/bash
river=mississippi
highest=1
for model in H08 MPI-HM WBM PCR-GLOBWB
do
  for gcm in GFDL-ESM2M HadGEM2-ES IPSL-CM5A-LR MIROC-ESM-CHEM NorESM1-M
  do
    for scenario in hist rcp8p5 rcp4p5
    do
      RESULT=$(awk 'FNR==1 {print $4, FILENAME}' ${model}_${gcm}_${scenario}_${river}[1-9]/${model}_${gcm}_${scenario}_${river}[1-9].txt | sort -n -r| head -1) 
      highest="$(echo $RESULT | cut -d ' ' -f1 )"
      hifile="$(echo $RESULT | cut -d ' ' -f2 )"
      echo "highest was $highest in $hifile"
      cp "$hifile" "/home/stevens/SUMARIO/Fred/highest_discharge/${river}/${model}_${gcm}_${scenario}_${river}.txt"
    done
  done
done

Então, eu gostaria de adaptar este script de tal forma que ao invés de copiar o arquivo com o maior valor (na primeira linha, na quarta coluna), eu gostaria de copiar o arquivo com o maior valor médio no quarto. coluna, em comparação com os outros arquivos. Quaisquer sugestões ou conselhos são muito apreciados!

    
por steve 13.11.2015 / 17:57

2 respostas

1

Basta alterar a forma como você calcula RESULTADO:

RESULT=$(awk '{x+=$4} END{print x/NR, FILENAME}' ${model}_${gcm}_${scenario}_${river}[1-9]/${model}_${gcm}_${scenario}_${river}[1-9].txt | sort -n -r| head -1) 

O que isso faz: resume todos os valores da quarta linha e imprime no final o resultado dividido pelo número de linhas.

Como ele é dividido pelo número de linhas, você obterá resultados inesperados se tiver linhas vazias em seus arquivos: a soma não levará esses valores em consideração, mas a divisão será pelo número de linhas.

Editar:

Eu tive um erro em minha primeira tentativa que fez com que o script levasse em consideração apenas o máximo do último arquivo (porque END é executado depois que os arquivos ALL são processados)

Versão correta:

awk 'FNR==1 && NR>1 {print x/nr, file;x=0}{x+=$4; nr=FNR; file=FILENAME} END{print x/nr, file, x, nr}' ${model}_${gcm}_${scenario}_${river}[1-9]/${model}_${gcm}_${scenario}_${river}[1-9].txt | sort -n -r| head -1

Explicação:

  • imprimimos cada vez que o arquivo anterior é analisado. Como o FNR é zerado toda vez que um novo arquivo é lido, verificamos se começamos um novo arquivo (FNR == 1) e não estamos no primeiro arquivo (NR > 1). Nesse caso, imprimimos a média e o nome do arquivo salvos do arquivo anterior. Nós também resetamos x (onde mantemos a média)
  • caso contrário, começamos a calcular x. Também salvamos o número de registros neste arquivo (FNR) e o nome do arquivo
  • no final, imprimimos a média do último arquivo
por 17.11.2015 / 14:22
1

Parece que você já descobriu como segmentar as próprias colunas. Agora, tudo o que você precisa fazer é obter uma média da quarta coluna de todos os 4 arquivos e copiar aquela com a média mais alta (apenas uma espécie de reafirmar o que você já disse).

Basicamente, o que você precisa fazer é totalizar a saída da coluna 4 de cada um dos 4 arquivos e dividir pelo número de linhas da coluna 4 para obter a média. Em seguida, copie o arquivo com a maior média.

Espero que você esteja apenas querendo saber como obter a média, correto?

É fácil obter o número de linhas fazendo algo como echo "$file1_col4" | wc -l ou wc -l <<< "$file1_col4" , o que você já deveria ter. Armazene cada um em uma variável para dividir por mais tarde. Então, vamos apenas dizer isto:

file1_col4_rows=$(echo "$file1_col4" | wc -l) 

Para obter o total da coluna, você faria o seguinte:

file1_col4_total=$(echo "$file1_col4" | awk '{total = total + $1}END{print total}')

Você faria isso para todos os 4 arquivos e dividiria pelo número total de linhas na coluna que você definiu como a variável anterior. O Bash tem um built-in para lidar com isso, mas eu prefiro usar perl :

file1_avg=$(perl -e "print $file1_col4_total/$file1_col4_rows")

Ao fazer isso para todos os 4 arquivos, você pode ver facilmente qual arquivo teve a quarta coluna média mais alta referenciando as variáveis $fileN_avg e, em seguida, copiar o arquivo que tem a variável com o maior valor:

file_to_copy="$(echo "file1 $file1_avg
file2 $file2_avg
file3 $file3_avg
file4 $file4_avg" |
sort -nrk2 |
head -1 |
awk '{print $1}')"

Em seguida, basta cp "$file_to_copy" /path/where/it/belongs/

    
por 20.11.2015 / 05:53

Tags