Desvio padrão do número ao lado de um padrão

0

Eu tenho um arquivo com muitas tags com um número próximo a elas, definido assim:

<Score>4
... other data
<Score>2
... other data
<Score>3

e assim por diante ...

Eu usei o grep para obter o número de vezes que aparece em uma linha

grep -c '<Score>' $1

e calculei a soma das pontuações usando o awk:

awk 'sub(/<Score>/,""){y+=$0} END{print y}' $1}

e, em seguida, dividi-lo pelo número que recebi do grep para obter a média.

O que estou enfrentando é como tirar a média de cada valor ao lado de < Score & gt ;, enquadrando-o e, em seguida, somando-o juntos.

A média é armazenada na variável $ mean O código que tentei é assim:

awk 'sub(/<Score>/,""){y+=($0-$mean)^2} END{print y}' $1

No entanto, ele mantém a saída 0, se eu conseguir armazenar isso em uma variável, então poderei calcular o desvio padrão, usando todas as minhas outras variáveis.

    
por tom 21.02.2016 / 17:28

1 resposta

0

Aqui estão alguns utilitários para você. O primeiro calcula a média dos números dados a ele (um número por linha). O segundo usa o primeiro para calcular o desvio padrão dos números em um arquivo.

O arquivo executável average :

#!/usr/bin/awk -f

/^[0-9.+-]/     { sum += $0; ++n }

END             { print sum / n }

Este script awk lerá a entrada de um arquivo ou da entrada padrão e calculará a média dos números nela. Espera um número por linha.

O arquivo executável stdev :

#!/bin/sh

awk -v avg="$( ./average "$1" )" \
    '/^[0-9.+-]/ { sum += ($0 - avg)^2; ++n }
     END         { print sqrt(sum / (n - 1)) }' "$1"

Este script de shell primeiro usará o script average acima para calcular a média dos dados no arquivo fornecido na linha de comando. Esse número é atribuído à awk variable avg . Em seguida, ele usa o mesmo tipo de detecção de número que o script average para calcular o desvio padrão.

Como este script está escrito agora, ele requer dados de um arquivo, não de uma entrada padrão.

Uma maneira de usar isso em seus dados:

sed -n '/^<Score>/s///p' input.dat >output.dat

Com os dados fornecidos, isso gerará um arquivo chamado output.dat contendo o seguinte:

4
2
3

Usando o script stdev acima neste arquivo:

$ ./stdev output.dat
1

O que está correto, até onde eu posso ver.

Claro, você pode fazer isso diretamente em uma chamada awk , sem criar qualquer tipo de ferramenta reutilizável:

awk -F '>' '/^<Score>/ { v[++n] = $2; s += $2 }
            END { avg = s/n;
                  for (i=1; i<=n; ++i) {
                      std += (v[i] - avg)^2;
                  }
                  print sqrt(std / (n - 1));
                 }' input.dat
    
por 20.09.2017 / 22:45