J'ai une liste de numéros dans un fichier, un par ligne. Comment puis-je obtenir les valeurs minimale, maximale, médiane et moyenne ? Je veux utiliser les résultats dans un script bash.
Bien que ma situation immédiate concerne les nombres entiers, une solution pour les nombres à virgule flottante serait utile en bout de ligne, mais une méthode de nombre entier simple convient parfaitement.
bash
awk
arithmetic
bc
Peter.O
la source
la source
Réponses:
Vous pouvez utiliser le langage de programmation R .
Voici un script rapide et sale:
Notez le
"stdin"
dansscan
lequel se trouve un nom de fichier spécial à lire à partir d’une entrée standard (c’est-à-dire à partir de pipes ou de redirections).Vous pouvez maintenant rediriger vos données sur stdin vers le script R:
Fonctionne également pour les points flottants:
Si vous ne voulez pas écrire de fichier de script R, vous pouvez appeler une vraie ligne (avec un saut de ligne uniquement pour la lisibilité) dans la ligne de commande en utilisant
Rscript
:Lisez les manuels R fins sur http://cran.r-project.org/manuals.html .
Malheureusement, la référence complète est uniquement disponible en PDF. Une autre façon de lire la référence consiste à saisir
?topicname
l'invite d'une session interactive R.Pour être complet: il existe une commande R qui affiche toutes les valeurs souhaitées et plus encore. Malheureusement, dans un format convivial, difficile à analyser par programmation.
la source
r-base
.R
la langue est clairement le meilleur pour mon besoin dans cette situation .. Selon la réponse de Gilles, l'Rscript
interface pour les fichiers de script est la plus appropriée (vsR
, qui est l'interface interactive) ... et R dans le terminal constitue une calculatrice pratique , ou environnement de test (comme python :)cat datafile | Rscript -e 'print(summary(scan("stdin")));'
En fait, je garde un petit programme awk pour donner la somme, le nombre de données, le minimum de données, le maximum de données, la moyenne et la médiane d'une seule colonne de données numériques (y compris les nombres négatifs):
Le script ci-dessus lit à partir de stdin et imprime les colonnes de sortie séparées par des tabulations sur une seule ligne.
la source
NR==1
pouvez y aller (une utilisation inutile de si) ainsi que les vérifications min / max, ainsi toutes les initialisations peuvent être situées dans la section BEGIN (bon!) ... Permettre des commentaires est une belle touche aussi .. Merci, +1 ...awk
supposons que les "nouvelles" variables sont à zéro, de sorte que dans ce cas, laBEGIN{}
section est inutile. J'ai corrigé l'emballage (pas besoin d'échapper aux sauts de ligne). J'avais aussi l'habitudeOFS="\t"
de nettoyer laprint
ligne et de mettre en œuvre le deuxième commentaire de @ Peter.O. (Oui, ma regex le permet.
, mais commeawk
interprété0
, c'est acceptable.)awk
script est maintenant sensiblement différent. J'ai presque l'impression que vous devriez prendre crédit pour le programme ci-dessus, afin de donner un crédit lorsque le crédit est dû.Avec GNU datamash :
la source
brew install datamash
vous donne une version de travail pour macOS, si vous avez installé Hombrew.Min, max et average sont assez faciles à obtenir avec awk:
Le calcul de la médiane est un peu plus délicat, car vous devez trier les nombres et les stocker tous en mémoire pendant un moment ou les lire deux fois (première fois à les compter, deuxième - pour obtenir la valeur médiane). Voici un exemple qui stocke tous les nombres en mémoire:
la source
asort
plutôt que le pipedsort
Voici un lien vers ma version résultante paste.ubuntu.com/612674 ... (et une note à Kim: je teste awk depuis quelques heures maintenant Travailler avec un exemple d’intérêt personnel est bien mieux pour moi) ... Une note générale aux lecteurs: Je suis toujours intéressé de voir d’autres méthodes. le plus compact le mieux. Je vais attendre un peu ...pythonpy fonctionne bien pour ce genre de chose:
la source
Le minimum:
Maximum:
Médian:
Moyenne:
Dans
jq
l' option-s
(--slurp
), un tableau est créé pour les lignes d'entrée après l'analyse de chaque ligne sous forme de code JSON ou sous forme de nombre dans ce cas.la source
la source
echo file.txt
ne semble pas tout à fait raison, peutcat
Et une doublure (longue) en Perl, y compris la médiane:
Les options spéciales utilisées sont:
-0777
: lit le fichier entier en une fois au lieu de ligne par ligne-a
: autosplit dans le tableau @FUne version de script plus lisible de la même chose serait:
Si vous voulez des nombres décimaux, remplacez-les
%d
par quelque chose comme%.2f
.la source
Simple-r est la réponse:
Il utilise l'environnement R pour simplifier l'analyse statistique.
la source
Juste pour avoir une variété d’options présentées sur cette page, voici encore deux façons:
1: octave
Voici un exemple rapide d'octave.
2: bash + outils à usage unique .
Pour que bash puisse gérer les nombres à virgule flottante, ce script utilise
numprocess
etnumaverage
depuis le packagenum-utils
.PS J'ai également examiné de manière raisonnable
bc
, mais pour ce travail particulier, il n'offre rien de plus que ce qu'ilawk
propose. C'est (comme le dit le 'c' dans 'bc') une calculatrice - une calculatrice qui nécessite beaucoup de programmation commeawk
et ce script bash ...la source
Je seconderai le choix de R de Lesmana et offrirai mon premier programme de R. Il lit un numéro par ligne sur l'entrée standard et écrit quatre nombres (min, max, moyenne, médiane) séparés par des espaces sur la sortie standard.
la source
R
interface interactive, etRscript
pilotait les fichiers scriptés, qui pouvaient être exécutés selon votre exemple hash-bang , ou invoqués depuis un script bash .. Les scripts peuvent gérer les arguments en ligne de commande (par exemple, stackoverflow.com/questions/2045706/… ) afin que tout soit beau ... Les expressions R peuvent également être utilisées dans bash via-e
... mais Je me demande comment seR
compare àbc
...Le dessous
sort
/awk
tandem le fait:(il calcule la médiane comme moyenne des deux valeurs centrales si le nombre de valeurs est pair)
la source
En prenant exemple sur le code de Bruce, voici une implémentation plus efficace qui ne conserve pas l'intégralité des données en mémoire. Comme indiqué dans la question, cela suppose que le fichier d'entrée a (au plus) un nombre par ligne. Il compte les lignes du fichier d'entrée contenant un numéro de qualification et transmet le compte à la
awk
commande avec (précédent) les données triées. Ainsi, par exemple, si le fichier contientalors l'entrée
awk
est en faitEnsuite, le
awk
script capture le nombre de données dans leNR==1
bloc de code et enregistre la valeur médiane (ou les deux valeurs médianes, dont la moyenne est calculée pour obtenir la médiane) lorsqu'il les voit.la source
cat
commandes inutiles ; voir UUOC . … (Suite)FILENAME
et vous savez comment vous le définissez, mais, en général, vous devez toujours citer les variables de shell à moins que vous n'ayez une bonne raison de ne pas le faire et Bien sûr, vous savez ce que vous faites. (4) Votre réponse et celle de Bruce ignorent toutes les entrées négatives (c'est-à-dire les nombres commençant par-
); rien dans la question n'indique qu'il s'agit d'un comportement correct ou souhaité. Ne te sens pas mal. Cela fait plus de quatre ans et, apparemment, je suis la première personne à l'avoir remarqué.cat
et ajouté à l'explication.Le
num
est un petitawk
emballage qui fait exactement cela et plus, par exemplecela vous évite de réinventer la roue dans l'awk ultra-portable. Les documents sont donnés ci-dessus, et le lien direct ici (voir aussi la page GitHub ).
la source
Avec
perl
:la source
cat/python
seule solution - pas de preuve d'entrée vide!la source
Si vous êtes plus intéressé par l'utilité que par la fraîcheur ou l'intelligence, le
perl
choix est plus facile queawk
. En gros, ce sera sur chaque * nix avec un comportement cohérent, et est facile et gratuit à installer sur Windows. Je pense que c'est aussi moins crypté queawk
, et il y aura quelques modules de statistiques que vous pourriez utiliser si vous vouliez une maison de transition entre l'écrire vous-même et quelque chose comme R. Mon assez peu testé (en fait je sais qu'il a des bugs mais qu'il fonctionne pour mes besoins ) leperl
script a pris environ une minute pour écrire, et je suppose que la seule partie cryptique serait lewhile(<>)
, qui est le raccourci très utile, ce qui signifie prendre le (s) fichier (s) passé (s) en tant qu'argument de ligne de commande, lire une ligne à la fois et mettre cette ligne dans la variable spéciale$_
. Donc, vous pouvez mettre cela dans un fichier nommé count.pl et l'exécuter en tant queperl count.pl myfile
. En dehors de cela, il devrait être douloureusement évident de savoir ce qui se passe.la source
la source
sh
) comme interprète. Il y a également un problème avec la façon dont les données sont lues dans le tableau à partir du fichier.