Calcule o valor médio de uma coluna e diga se esse valor é “OK” ou “ERROR” se estiver dentro da faixa aceitável

3

Eu gostaria de calcular o valor mediano de uma coluna específica em um arquivo .txt, gerar esse valor e dizer também se esse valor de saída é ok. Eu posso fazer os passos iniciais e produzir o valor mediano, no entanto, ele não pode dizer se o valor de saída está dentro do intervalo aceitável.

Eu recebo uma mensagem de erro de sintaxe com o seguinte código:

sort -nk9 filename | awk '{a[i++]=$9;} END {x=int((i+1)/2); y=((a[x-1] + a[x])/2); z=(a[x-1]);
if ((y >= 0.5 && y <= 2) || (z >= 0.5 && z <=2));
   {if (x < (i+1)/2) 
   print "Median OR =", y "ALL OK"; 
   else print "Median OR =", z "ALL OK"}; 
else print "ERROR - OR outside range 0.5 - 2.0"}'
    
por Bob 07.11.2014 / 05:26

2 respostas

3

Eu acho que isso é o que você quer

awk '{sum+=$9;a[x++]=$9;b[$9]++}b[$9]>Mode{Mode=$9}END{print "Mean: " sum/x "\nMedian: "a[int((x-1)/2)]"\nMode: " Mode}' file

Deitado mais limpo

awk '
{
     sum+=$9
     a[x++]=$9
     b[$9]++
}
b[$9]>Mode{Mode=$9}
END{
    print "Mean: " sum/x 
    print "Median: "a[int((x-1)/2)] 
    print "Mode: " Mode
}' file

Além disso, adicionarei alguma lógica para as comparações, mas na verdade não sei o que você está tentando comparar, já que suas variáveis são chamadas x, y, z e do podem ou não ter as equações corretas

    
por 07.11.2014 / 16:38
2

Agradeço o código user78605 que forneceu, pois ele me orientou sobre como encontrar a mediana em minhas consultas. O código acima mencionado, no entanto, ignora certas condições que são necessárias para calcular a mediana corretamente.

Problemas:

  1. As linhas finais em branco (se existirem no arquivo) não devem ser contadas, pois contá-las afeta o tamanho dos dados e, portanto, a média, a mediana, o modo e outras quantidades estatísticas. O mesmo provavelmente deve ser feito para as linhas que não possuem valores numéricos (id est: "abc" , "28b" , "h2f" , "" e et cetera).
  2. A mediana é o valor médio de não o conjunto de dados original, mas um conjunto de dados ordenado. Ou seja, os dados para os quais a mediana deve ser encontrada devem ser classificados primeiro.
  3. Se a quantidade de valores em um conjunto de dados ordenado for par, a média dos dois valores intermediários deve ser tomada.
  4. O modo é um valor com a maior frequência. É possível que o conjunto de dados tenha mais de um modo, em cujo caso dois ou mais valores precisam ser listados como modo.

A seguir, minha expansão do código, levando em conta as condições mencionadas acima:

awk -F',' '
{col=$1}{if((col ~  /^-?[0-9]*([.][0-9]+)?$/) && ($0!=""))                 
{
     sum+=col;
     a[x++]=col;
     b[col]++
     if(b[col]>hf){hf=b[col]}
}
}
END{n = asort(a);idx=int((x+1)/2)
     print "Mean: " sum/x
     print "Median: " ((idx==(x+1)/2) ? a[idx] : (a[idx]+a[idx+1])/2)
     for (i in b){if(b[i]==hf){(k=="") ? (k=i):(k=k FS i)}{FS=","}}
     print "Mode: " k
}' file

EXPLICAÇÃO:

Solução para o problema nº 1:

col=$1 #easier to change columns if stored in a variable.
(col ~ /^-?[0-9]*([.][0-9]+)?$/) #The string must only comprise numerals, a period (decimal separator), or a dash (minus sign). [Only the scientific notation is overlooked.]
($0!="") #the entire row must not be blank.

Nas linhas elegíveis, execute as seguintes operações de loop:

sum+=col #(Short for sum=sum+col.) Sum of all values.
a[x++]=col #Every value is stored into an array.
b[col]++ #Values in col are treated as surrogate keys of array b. Hence there are only as many elements in b as the number of unique values in col. This iterator creates an array of frequency counts. (Short for b[col]=b[col]+1.)
if(b[col]>hf){hf=b[col]} #Let hf stand for "the highest frequency". Loop through all the frequencies and update hf only if higher frequencies are found. hf is initially "" (nothing).

Solução para o problema nº 2:
Depois que as operações de loop forem concluídas:

Sort the values stored in the array: n = asort(a)

It is important to note that the original indices of array a ranged from "0" to "x-1". In addition to sorting, the new index range is from "1" to "x". This is why I use int((x+1)/2) instead of
int((x-1)/2) as the index which holds the median - or the smaller of the two numbers which will be averaged out to a median.

Solução para o problema nº 3:

((idx == (x+1)/2) ? a[idx] : (a[idx]+a[idx+1])/2)
This is a shorthand notation for an if-else construction:
If int((x+1)/2) equals (x+1)/2 then the number of values is odd, and the median will be a[idx]. If this is not so, int() will round down (x+1)/2 to the nearest integer signifying that the number of values is even. In this case, the average of a[idx] and a[idx]+1 will be the median.

Solução para o problema nº 4:

for (i in b) {if(b[i]==hf){(k=="") ? (k=i):(k=k FS i)}{FS=","}}
Since hf is the value which represents the highest frequency in the data set, if any value of b is equal to hf, its surrogate key is the mode, or at least one of the modes.
This code concatenates all surrogate keys, i, which match the criterion and stores them into a variable, k, that can be printed on one row with the title "Mode".

Outros ajustes:

-F deve ser ajustado de acordo com o caractere que estiver sendo usado como separador de coluna no arquivo.

Se o arquivo tiver cabeçalhos na primeira linha, adicione NR > 1 na frente de {col=$1} .

FS foi usado para concatenar duas variáveis juntas. O uso de FS é especialmente útil quando se escolhe não usar o separador. Isto é, FS="" .

Dados

Os seguintes dados foram usados para experimentação para criar o script:

10
20
10
20.5
50
30
40
50
10
30
20.5


-h
h

4.35
-537
0
-0

30
d




.

RESULTADOS:

Mean: -13.2281
Median: 20.25
Mode: 10,30
    
por 18.07.2015 / 08:29

Tags