Eu tenho uma lista de números em um arquivo, um por linha. Como obtenho os valores mínimo, máximo, mediano e médio ? Eu quero usar os resultados em um script bash.
Embora minha situação imediata seja para números inteiros, uma solução para números de ponto flutuante seria útil na linha, mas um método inteiro simples é bom.
bash
awk
arithmetic
bc
Peter.O
fonte
fonte
Respostas:
Você pode usar a linguagem de programação R .
Aqui está um script R rápido e sujo:
Observe o nome do arquivo
"stdin"
emscan
que é especial para ler da entrada padrão (que significa de pipes ou redirecionamentos).Agora você pode redirecionar seus dados sobre stdin para o script R:
Também funciona para pontos flutuantes:
Se você não quiser escrever um arquivo de script R, poderá chamar uma linha única (com quebra de linha apenas para facilitar a leitura) na linha de comando usando
Rscript
:Leia os bons manuais do R em http://cran.r-project.org/manuals.html .
Infelizmente, a referência completa está disponível apenas em PDF. Outra maneira de ler a referência é digitando
?topicname
o prompt de uma sessão R interativa.Para completar: existe um comando R que gera todos os valores que você deseja e muito mais. Infelizmente, em um formato amigável para humanos, difícil de analisar de forma programática.
fonte
r-base
.R
a linguagem é claramente a melhor para o meu requisito nesta situação. Conforme a resposta de Gilles, aRscript
interface para arquivos de script é mais apropriada (vs.R
, que é a interface interativa) ... e R no terminal é uma calculadora útil ou ambiente de teste (como python :)cat datafile | Rscript -e 'print(summary(scan("stdin")));'
Na verdade, eu mantenho um pequeno programa awk para fornecer a soma, contagem de dados, dado mínimo, número máximo, média e mediana de uma única coluna de dados numéricos (incluindo números negativos):
O script acima lê de stdin e imprime colunas de saída separadas por tabulação em uma única linha.
fonte
NR==1
pode continuar (um uso inútil de- if) junto com as verificações min / max, para que toda a inicialização possa ser localizada na seção BEGIN (boa!) ... Permitir comentários também é um toque agradável .. Obrigado, +1 ...awk
assumirá que "novas" variáveis são zero, portanto, neste caso, aBEGIN{}
seção é desnecessária. Corrigi o empacotamento (não é necessário escapar das quebras de linha). Eu também costumavaOFS="\t"
limpar aprint
linha e implementou o segundo comentário de @ Peter.O. (Sim, meu regex permite.
, mas comoawk
interpreta isso como0
, isso é aceitável.)awk
script agora é substancialmente diferente. Eu quase sinto que você deve receber crédito pelo programa acima, a fim de dar crédito onde o crédito é devido.Com o GNU datamash :
fonte
brew install datamash
fornece uma versão funcional para o macOS, se você tiver o Hombrew instalado.Mín, max e média são muito fáceis de obter com o awk:
O cálculo da mediana é um pouco mais complicado, pois você precisa classificar os números e armazená-los todos na memória por um tempo ou lê-los duas vezes (primeira vez para contá-los, segundo - para obter valor mediano). Aqui está um exemplo que armazena todos os números na memória:
fonte
asort
vez do canalizadosort
e parece classificar números inteiros e decimais corretamente. Aqui está um link para a minha versão resultante paste.ubuntu.com/612674 ... (E uma observação para Kim: eu estou experimentando o awk há algumas horas Trabalhar com um exemplo de interesse pessoal é muito melhor para mim) ... Uma observação geral para os leitores: Ainda estou interessado em ver outros métodos. quanto mais compacto, melhor. Vou esperar um pouco ...pythonpy funciona bem para esse tipo de coisa:
fonte
Mínimo:
Máximo:
Mediana:
Média:
Em
jq
a-s
(--slurp
opção) cria uma matriz para as linhas de entrada depois de analisar cada linha como JSON, ou como um número, neste caso.fonte
fonte
echo file.txt
não parece muito bem, talvezcat
E um liner único (longo) do Perl, incluindo a mediana:
As opções especiais usadas são:
-0777
: leia o arquivo inteiro de uma só vez em vez de linha por linha-a
: divisão automática na matriz @FUma versão de script mais legível da mesma coisa seria:
Se você quiser decimais, substitua
%d
por algo como%.2f
.fonte
Simple-r é a resposta:
Ele usa o ambiente R para simplificar a análise estatística.
fonte
Apenas para apresentar uma variedade de opções nesta página, aqui estão mais duas maneiras:
1: oitava
Aqui está um exemplo rápido de oitava.
2: bash + ferramentas de uso único .
Para o bash manipular números de ponto flutuante, esse script usa
numprocess
enumaverage
from packagenum-utils
.PS. Também tive uma visão razoável
bc
, mas para esse trabalho em particular, ele não oferece nada além do queawk
faz. É (como o 'c' em 'bc' afirma) uma calculadora - uma calculadora que requer muita programaçãoawk
e esse script bash ...fonte
Vou escolher a segunda opção para R de lesmana e oferecer meu primeiro programa de R. Ele lê um número por linha na entrada padrão e grava quatro números (min, max, média, mediana) separados por espaços na saída padrão.
fonte
R
é a interface interativa eRscript
dirige os arquivos com script, que podem ser executáveis conforme o seu exemplo hash-bang , ou invocado a partir de um script bash. Os scripts podem manipular argumentos da linha de comandos (por exemplo, stackoverflow.com/questions/2045706/… ), para que pareça bom ... Também expressões R podem ser usadas no bash por meio do-e
... mas pergunto-me comoR
se compara abc
...O abaixo
sort
/awk
tandem faz isso:(calcula mediana como média dos dois valores centrais se a contagem de valores for par)
fonte
Tomando dicas do código de Bruce, aqui está uma implementação mais eficiente que não mantém todos os dados na memória. Conforme declarado na pergunta, ele assume que o arquivo de entrada possui (no máximo) um número por linha. Ele conta as linhas no arquivo de entrada que contêm um número qualificado e passa a contagem para o
awk
comando junto com (precedendo) os dados classificados. Então, por exemplo, se o arquivo contiverentão a entrada para
awk
é realmenteEm seguida, o
awk
script captura a contagem de dados noNR==1
bloco de código e salva o valor do meio (ou os dois valores do meio, que são calculados para gerar a mediana) quando os vê.fonte
cat
comandos desnecessários ; veja UUOC . ... (continua)FILENAME
e sabe o que definir, mas, em geral, sempre deve citar variáveis de shell, a menos que tenha um bom motivo para não fazê-lo e você Certifique-se que você sabe o que está fazendo. (4) Sua resposta e a de Bruce ignoram dados negativos (ou seja, números começando com-
); não há nada na pergunta que sugira que esse seja o comportamento correto ou desejado. Não se sinta mal; já faz mais de quatro anos e, aparentemente, sou a primeira pessoa que percebi.cat
e adicionei à explicação.O
num
é umawk
invólucro minúsculo que faz exatamente isso e muito mais, por exemploevita que você reinvente a roda no awk ultra-portátil. Os documentos são fornecidos acima e o link direto aqui (consulte também a página do GitHub ).
fonte
Com
perl
:fonte
cat/python
única solução - não prova de entrada vazia!fonte
Se você está mais interessado em utilidade do que em ser legal ou inteligente, então
perl
é uma escolha mais fácil do queawk
. Em geral, ele estará em todos os * nix com comportamento consistente e é fácil e gratuito para instalar no Windows. Eu acho que também é menos enigmático do queawk
, e haverá alguns módulos de estatísticas que você poderia usar se quisesse uma casa intermediária entre escrevê-lo e algo como R. )perl
demorou cerca de um minuto para escrever, e eu acho que a única parte enigmática seria awhile(<>)
, que é a abreviação muito útil, ou seja, pegar os arquivos passados como argumentos de linha de comando, ler uma linha de cada vez e colocar essa linha na variável especial$_
. Então você pode colocar isso em um arquivo chamado count.pl e executá-lo comoperl count.pl myfile
. Além disso, deve ser dolorosamente óbvio o que está acontecendo.fonte
fonte
sh
) como intérprete. Há também um problema com a forma como os dados são lidos na matriz a partir do arquivo.