Mam listę liczb w pliku, po jednym w wierszu. Jak mogę uzyskać wartości minimalną, maksymalną, medianę i średnią ? Chcę użyć wyników w skrypcie bash.
Chociaż moja bezpośrednia sytuacja dotyczy liczb całkowitych, rozwiązanie dla liczb zmiennoprzecinkowych byłoby przydatne wzdłuż linii, ale prosta metoda na liczbach całkowitych jest w porządku.
bash
awk
arithmetic
bc
Peter.O
źródło
źródło
Odpowiedzi:
Można użyć języka programowania R .
Oto szybki i brudny skrypt R:
Uwaga:
"stdin"
wscan
której znajduje się specjalna nazwa pliku do odczytu ze standardowego wejścia (to znaczy z potoków lub przekierowań).Teraz możesz przekierować swoje dane przez stdin do skryptu R.
Działa również dla zmiennoprzecinkowych:
Jeśli nie chcesz pisać pliku skryptu R, możesz wywołać prawdziwą jednowierszową (z podziałką tylko dla czytelności) w wierszu poleceń, używając
Rscript
:Przeczytaj dokładne instrukcje R na stronie http://cran.r-project.org/manuals.html .
Niestety pełne odniesienie jest dostępne tylko w formacie PDF. Innym sposobem na odczytanie referencji jest wpisanie
?topicname
pytania w interaktywnej sesji R.Dla kompletności: istnieje polecenie R, które wyświetla wszystkie potrzebne wartości i więcej. Niestety w przyjaznym dla człowieka formacie, który jest trudny do analizowania programowo.
źródło
r-base
.R
język jest zdecydowanie najlepszy dla moich wymagań w tej sytuacji. Zgodnie z odpowiedzią GillesaRscript
interfejs do plików skryptowych jest najbardziej odpowiedni (w przeciwieństwieR
do interfejsu interaktywnego) ... a R w terminalu stanowi przydatny kalkulator lub środowisko testowe (takie jak python :)cat datafile | Rscript -e 'print(summary(scan("stdin")));'
Właściwie trzymam mały program awk, aby podać sumę, liczbę danych, minimalny układ odniesienia, maksymalny układ odniesienia, średnią i medianę pojedynczej kolumny danych liczbowych (w tym liczb ujemnych):
Powyższy skrypt czyta ze standardowego wejścia i wypisuje rozdzielone tabulatorami kolumny wyników w jednym wierszu.
źródło
NR==1
można przejść (bezużyteczne użycie if) wraz z kontrolami min / max, więc cała inicjalizacja może być zlokalizowana w sekcji BEGIN (dobrze!) ... Pozwolenie na komentarze też jest miłym akcentem. Dzięki, +1 ...awk
zakłada , że „nowe” zmienne są zerowe, więc w tym przypadkuBEGIN{}
sekcja nie jest potrzebna. Naprawiłem zawijanie (nie ma też potrzeby ucieczki przed łamaniem linii). Ja równieżOFS="\t"
wyczyściłemprint
linię i zaimplementowałem drugi komentarz @ Peter.O. (Tak, moje wyrażenie regularne na to pozwala.
, ale coawk
interpretuje to jako0
akceptowalne.)awk
skrypt jest teraz zupełnie inny. Wydaje mi się, że powinieneś wziąć kredyt na powyższy program, aby przyznać kredyt tam, gdzie jest on należny.Z GNU datamash :
źródło
brew install datamash
daje działającą wersję dla systemu macOS, jeśli masz zainstalowany Hombrew.Z awk można łatwo uzyskać min, maks i średnią:
Obliczanie mediany jest nieco trudniejsze, ponieważ musisz sortować liczby i przechowywać je wszystkie w pamięci przez chwilę lub przeczytać je dwa razy (pierwszy raz, aby je policzyć, drugi - aby uzyskać wartość mediany). Oto przykład, który przechowuje wszystkie liczby w pamięci:
źródło
asort
zamiast pipedsort
, i wydaje się, że poprawnie sortuje liczby całkowite i dziesiętne. Oto link do mojej wynikowej wersji paste.ubuntu.com/612674 ... (I uwaga dla Kim: eksperymentuję z awk od kilku godzin Praca z przykładem interesu osobistego jest dla mnie znacznie lepsza) ... Ogólna uwaga dla czytelników: Nadal jestem zainteresowany innymi metodami. im bardziej kompaktowy, tym lepiej. Zaczekam chwilę ...Pythonpy działa dobrze dla tego rodzaju rzeczy:
źródło
Minimum:
Maksymalny:
Mediana:
Średni:
W
jq
opcji-s
(--slurp
) tworzy tablicę dla linii wejściowych po parsowaniu każdej linii jako JSON lub w tym przypadku jako liczbę.źródło
źródło
echo file.txt
nie wygląda całkiem dobrze, możecat
I jeden (długi) liniowiec Perla, w tym mediana:
Zastosowano specjalne opcje:
-0777
: czytaj cały plik na raz zamiast linii po linii-a
: autosplit do tablicy @FBardziej czytelną wersją skryptu tego samego byłoby:
Jeśli chcesz miejsc po przecinku, zamień na
%d
coś podobnego%.2f
.źródło
Prosta r jest odpowiedzią:
Wykorzystuje środowisko R w celu uproszczenia analizy statystycznej.
źródło
Ze względu na różnorodność opcji prezentowanych na tej stronie, oto jeszcze dwa sposoby:
1: oktawa
Oto przykład szybkiej oktawy.
2: bash + narzędzia jednofunkcyjne .
Aby bash obsługiwał liczby zmiennoprzecinkowe, ten skrypt używa
numprocess
inumaverage
z pakietunum-utils
.PS. Przyjrzałem się również rozsądnie
bc
, ale w przypadku tej konkretnej pracy nie oferuje nic poza tym, coawk
robi. Jest to (jak mówi „c” w „bc”) kalkulator - kalkulator, który wymaga dużo programowaniaawk
i tego skryptu bash ...źródło
Będę drugim wyborem R dla lesmany i zaoferuję mój pierwszy program R. Odczytuje jedną liczbę na linię na standardowym wejściu i zapisuje cztery liczby (min., Maks., Średnia, mediana) oddzielone spacjami na standardowe wyjście.
źródło
R
jest to interaktywny interfejs iRscript
napędza skrypty plików, które można wykonać zgodnie z twoim przykładem hash-bang lub wywoływane z poziomu skryptu bash. Skrypty mogą obsługiwać argumenty wiersza poleceń (np. stackoverflow.com/questions/2045706/... ), więc wygląda dobrze ... Również wyrażenia R mogą być używane w bashie przez-e
... ale Zastanawiam się, jakR
bc
Poniższy
sort
/awk
tandem robi to:(oblicza medianę jako średnią z dwóch wartości centralnych, jeśli liczba wartości jest parzysta)
źródło
Biorąc wskazówki z kodu Bruce'a, tutaj jest bardziej wydajna implementacja, która nie przechowuje wszystkich danych w pamięci. Jak stwierdzono w pytaniu, zakłada się, że plik wejściowy ma (najwyżej) jedną liczbę w wierszu. Zlicza wiersze w pliku wejściowym, które zawierają liczbę kwalifikującą, i przekazuje licznik do
awk
polecenia wraz z (poprzednimi) posortowanymi danymi. Na przykład, jeśli plik zawierawtedy wejście do
awk
jest w rzeczywistościNastępnie
awk
skrypt przechwytuje liczbę danych wNR==1
bloku kodu i zapisuje środkową wartość (lub dwie środkowe wartości, które są uśredniane w celu uzyskania mediany), gdy je widzi.źródło
cat
polecenia; patrz UUOC . … (Ciąg dalszy)FILENAME
i wiesz, co ustawiłeś, ale ogólnie powinieneś zawsze cytować zmienne powłoki, chyba że masz dobry powód, aby tego nie robić, i jesteś na pewno wiesz co robisz. (4) Zarówno twoja odpowiedź, jak i Bruce ignorują negatywne dane wejściowe (tj. Liczby zaczynające się od-
); w pytaniu nie ma nic, co sugerowałoby, że jest to prawidłowe lub pożądane zachowanie. Nie czuj się źle; minęły ponad cztery lata i najwyraźniej jestem pierwszą osobą, która to zauważyła.cat
i dodałem do wyjaśnienia.num
Jest małyawk
wrapper który robi dokładnie to i więcej, npratuje Cię przed odkryciem koła w ultra-przenośnym awk. Dokumenty są podane powyżej, a bezpośredni link tutaj (sprawdź także stronę GitHub ).
źródło
Z
perl
:źródło
cat/python
jedyne rozwiązanie - nie dowód pustego wejścia!źródło
Jeśli bardziej interesuje Cię użyteczność niż bycie fajnym lub sprytnym, to
perl
jest łatwiejszy wybór niżawk
. Zasadniczo będzie on na każdym * nixie ze stałym zachowaniem, i jest łatwy i darmowy do zainstalowania w systemie Windows. Myślę, że jest to również mniej tajemnicze niżawk
, i będzie kilka modułów statystyk, których możesz użyć, jeśli chcesz mieć dom w połowie drogi między pisaniem go samemu a czymś takim jak R. Mój dość niesprawdzony (w rzeczywistości wiem, że ma błędy, ale działa na moje potrzeby ) napisanieperl
skryptu zajęło około minuty, i sądzę, że jedyną tajemniczą częścią byłaby tawhile(<>)
, która jest bardzo przydatnym skrótem, co oznacza, że weźmiemy pliki przekazane jako argumenty wiersza poleceń, odczytujemy wiersz po kolei i wstawiamy ten wiersz w zmiennej specjalnej$_
. Możesz więc umieścić to w pliku o nazwie count.pl i uruchomić jakoperl count.pl myfile
. Poza tym to, co się dzieje, powinno być boleśnie oczywiste.źródło
źródło
sh
) jako interpretera. Istnieje również problem z tym, jak dane są wczytywane do tablicy z pliku.