답변:
R 프로그래밍 언어를 사용할 수 있습니다 .
빠르고 더러운 R 스크립트는 다음과 같습니다.
#! /usr/bin/env Rscript
d<-scan("stdin", quiet=TRUE)
cat(min(d), max(d), median(d), mean(d), sep="\n")
음 "stdin"
의 scan
표준 입력을 판독하는 특별한 이름 (즉 파이프 또는 리디렉션에서 수단).
이제 stdin을 통해 R 스크립트로 데이터를 리디렉션 할 수 있습니다.
$ cat datafile
1
2
4
$ ./mmmm.r < datafile
1
4
2
2.333333
부동 소수점에도 작동합니다.
$ cat datafile2
1.1
2.2
4.4
$ ./mmmm.r < datafile2
1.1
4.4
2.2
2.566667
R 스크립트 파일을 작성하지 않으려면 명령 줄에서 다음을 사용하여 진정한 단일 라이너 (가독성을 위해 줄 바꿈 포함)를 호출 할 수 있습니다 Rscript
.
$ Rscript -e 'd<-scan("stdin", quiet=TRUE)' \
-e 'cat(min(d), max(d), median(d), mean(d), sep="\n")' < datafile
1
4
2
2.333333
http://cran.r-project.org/manuals.html 에서 훌륭한 R 매뉴얼을 읽으십시오 .
불행히도 전체 참조는 PDF로만 제공됩니다. 참조를 읽는 또 다른 방법 ?topicname
은 대화식 R 세션의 프롬프트 에 입력 하는 것입니다.
완전성을 위해 : 원하는 모든 값 등을 출력하는 R 명령이 있습니다. 불행히도 프로그래밍 방식으로 구문 분석하기 어려운 인간 친화적 인 형식입니다.
> summary(c(1,2,4))
Min. 1st Qu. Median Mean 3rd Qu. Max.
1.000 1.500 2.000 2.333 3.000 4.000
r-base
.
R
Gilles의 답변에 따르면, Rscript
스크립트 파일에 대한 인터페이스가 가장 적합합니다 ( R
대화 형 인터페이스 인 vs. ). 터미널의 R은 편리한 계산기입니다. 또는 테스트 환경 (python :)
cat datafile | Rscript -e 'print(summary(scan("stdin")));'
실제로 작은 awk 프로그램을 유지하여 숫자 데이터의 단일 열 (음수 포함)의 합계, 데이터 수, 최소 데이텀, 최대 데이텀, 평균 및 중앙값을 제공합니다.
#!/bin/sh
sort -n | awk '
BEGIN {
c = 0;
sum = 0;
}
$1 ~ /^(\-)?[0-9]*(\.[0-9]*)?$/ {
a[c++] = $1;
sum += $1;
}
END {
ave = sum / c;
if( (c % 2) == 1 ) {
median = a[ int(c/2) ];
} else {
median = ( a[c/2] + a[c/2-1] ) / 2;
}
OFS="\t";
print sum, c, ave, median, a[0], a[c-1];
}
'
위의 스크립트는 stdin에서 읽고 탭으로 구분 된 출력 열을 한 줄에 인쇄합니다.
NR==1
(갈 수를 쓸모없는 사용이 외 ! 경우), 그래서 모든 초기화가 BEGIN 부분에서 (좋은 위치 할 수 있습니다) 최소 / 최대 검사와 함께 ... 의견을 허용하는 것은 좋은 터치가 너무 .. 감사합니다, +1 ...
awk
"새"변수가 0이라고 가정하므로이 경우 BEGIN{}
섹션이 필요하지 않습니다. 줄 바꿈을 수정했습니다 (줄 바꿈을 벗어날 필요가 없습니다). 또한 라인 OFS="\t"
을 정리하고 print
@ Peter.O의 두 번째 주석을 구현했습니다. (예, 내 정규 표현식은을 허용 .
하지만으로 awk
해석 할 0
수 있습니다.)
awk
스크립트는 이제 크게 다릅니다. 크레딧이 필요한 곳에서 크레딧을 제공하려면 위 프로그램에 대한 크레딧을 받아야한다고 생각합니다.
GNU datamash로 :
$ printf '1\n2\n4\n' | datamash max 1 min 1 mean 1 median 1
4 1 2.3333333333333 2
brew install datamash
Hombrew를 설치 한 경우 macOS 용 작업 버전을 제공합니다.
최소, 최대 및 평균은 awk로 쉽게 얻을 수 있습니다.
% echo -e '6\n2\n4\n3\n1' | awk 'NR == 1 { max=$1; min=$1; sum=0 }
{ if ($1>max) max=$1; if ($1<min) min=$1; sum+=$1;}
END {printf "Min: %d\tMax: %d\tAverage: %f\n", min, max, sum/NR}'
Min: 1 Max: 6 Average: 3,200000
중앙값을 계산하는 것은 조금 까다 롭습니다. 숫자를 정렬하고 잠시 동안 메모리에 모두 저장하거나 두 번 읽어야하기 때문입니다 (첫 번째는 세고, 두 번째는 중앙값을 얻음). 다음은 모든 숫자를 메모리에 저장하는 예입니다.
% echo -e '6\n2\n4\n3\n1' | sort -n | awk '{arr[NR]=$1}
END { if (NR%2==1) print arr[(NR+1)/2]; else print (arr[NR/2]+arr[NR/2+1])/2}'
3
asort
파이프 가 아닌 awk를 사용했습니다. sort
, 그리고 그것은 정수와 소수를 올바르게 정렬하는 것 같습니다. 여기 내 결과 버전 paste.ubuntu.com/612674에 대한 링크가 있습니다 ... (그리고 Kim에 대한 메모 : 나는 두 시간 동안 awk를 실험 해왔습니다 개인적인 관심사를 가지고 작업하는 것이 나에게 더 낫다.) 독자들에게주는 일반적인 참고 사항 : 나는 여전히 다른 방법을보고 싶어한다. 더 작을 수록 좋습니다. 잠시만 기다려
최저한의:
jq -s min
최고:
jq -s max
중앙값:
sort -n|awk '{a[NR]=$0}END{print(NR%2==1)?a[int(NR/2)+1]:(a[NR/2]+a[NR/2+1])/2}'
평균:
jq -s add/length
에서는 ( 옵션) JSON 각 라인을 파싱 한 후, 입력 라인 어레이를 생성하거나,이 경우의 수로.jq
-s
--slurp
nums=$(<file.txt);
list=(`for n in $nums; do printf "%015.06f\n" $n; done | sort -n`);
echo min ${list[0]};
echo max ${list[${#list[*]}-1]};
echo median ${list[${#list[*]}/2]};
echo file.txt
아마 잘 보이지 않을 수도 있습니다cat
그리고 중앙값을 포함한 Perl 1- (긴) 라이너 :
cat numbers.txt \
| perl -M'List::Util qw(sum max min)' -MPOSIX -0777 -a -ne 'printf "%-7s : %d\n"x4, "Min", min(@F), "Max", max(@F), "Average", sum(@F)/@F, "Median", sum( (sort {$a<=>$b} @F)[ int( $#F/2 ), ceil( $#F/2 ) ] )/2;'
사용되는 특수 옵션은 다음과 같습니다.
-0777
: 전체 파일을 한 줄씩 읽는 대신 한 번에 읽기-a
: @F 배열로 자동 분할같은 것의 더 읽기 쉬운 스크립트 버전은 다음과 같습니다.
#!/usr/bin/perl
use List::Util qw(sum max min);
use POSIX;
@F=<>;
printf "%-7s : %d\n" x 4,
"Min", min(@F),
"Max", max(@F),
"Average", sum(@F)/@F,
"Median", sum( (sort {$a<=>$b} @F)[ int( $#F/2 ), ceil( $#F/2 ) ] )/2;
소수를 원하면 %d
다음과 같이 바꾸십시오 %.2f
.
이 페이지에 제시된 다양한 옵션을 위해 두 가지 방법이 더 있습니다.
1 : 옥타브
다음은 빠른 옥타브 예제입니다.
octave -q --eval 'A=1:10;
printf ("# %f\t%f\t%f\t%f\n", min(A), max(A), median(A), mean(A));'
# 1.000000 10.000000 5.500000 5.500000
2 : bash + 단일 목적 도구 .
bash는 부동 소수점 숫자를 처리하는 경우,이 스크립트는 사용 numprocess
및 numaverage
패키지 num-utils
.
추신. 또한 합리적으로 살펴 bc
보았지만이 특정 직업에 대해서는 그 이상을 제공 awk
하지 않습니다. 그것은 ( 'bc'상태에서 'c'로) 계산기입니다-계산기 awk
와 많은 bash 스크립트 가 필요한 계산기입니다 ...
arr=($(sort -n "LIST" |tee >(numaverage 2>/dev/null >stats.avg) ))
cnt=${#arr[@]}; ((cnt==0)) && { echo -e "0\t0\t0\t0\t0"; exit; }
mid=$((cnt/2));
if [[ ${cnt#${cnt%?}} == [02468] ]]
then med=$( echo -n "${arr[mid-1]}" |numprocess /+${arr[mid]},%2/ )
else med=${arr[mid]};
fi # count min max median average
echo -ne "$cnt\t${arr[0]}\t${arr[cnt-1]}\t$med\t"; cat stats.avg
lesmana가 선택한 R을 두 번째로 하고 첫 번째 R 프로그램을 제공 하겠습니다 . 표준 입력에서 한 줄에 하나의 숫자를 읽고 공백으로 구분 된 4 개의 숫자 (최소, 최대, 평균, 중앙값)를 표준 출력에 씁니다.
#!/usr/bin/env Rscript
a <- scan(file("stdin"), c(0), quiet=TRUE);
cat(min(a), max(a), mean(a), median(a), "\n");
R
. 대화식 인터페이스 인 직선을 인식하지 못하고 Rscript
스크립트 파일을 구동하므로 예제가 유용했습니다. , 또는 bash 스크립트 내에서 호출됩니다. 스크립트는 명령 줄 인수 (예 : stackoverflow.com/questions/2045706/… )를 처리 할 수 있으므로 좋아 보입니다 ... 또한 R 표현식은 bash에서 -e
...을 통해 사용할 수 있습니다 . 어떻게 궁금해 않는 R
비교에 bc
...
Bruce의 코드에서 힌트를 얻은 다음은 전체 데이터를 메모리에 보관하지 않는보다 효율적인 구현입니다. 질문에서 언급했듯이 입력 파일에는 줄당 하나의 숫자가 있다고 가정합니다. 규정 된 숫자를 포함하는 입력 파일의 행을 계수 awk
하고 정렬 된 데이터와 함께 (앞에) 계수를 명령에 전달합니다 . 예를 들어 파일에
6.0
4.2
8.3
9.5
1.7
입력 awk
은 실제로
5
1.7
4.2
6.0
8.3
9.5
그런 다음 awk
스크립트는 NR==1
코드 블록 에서 데이터 수를 캡처하고 중간 값 (또는 평균을 산출하는 평균 인 두 개의 중간 값)을 볼 때 저장합니다.
FILENAME="Salaries.csv"
(awk 'BEGIN {c=0} $1 ~ /^[-0-9]*(\.[0-9]*)?$/ {c=c+1;} END {print c;}' "$FILENAME"; \
sort -n "$FILENAME") | awk '
BEGIN {
c = 0
sum = 0
med1_loc = 0
med2_loc = 0
med1_val = 0
med2_val = 0
min = 0
max = 0
}
NR==1 {
LINES = $1
# We check whether numlines is even or odd so that we keep only
# the locations in the array where the median might be.
if (LINES%2==0) {med1_loc = LINES/2-1; med2_loc = med1_loc+1;}
if (LINES%2!=0) {med1_loc = med2_loc = (LINES-1)/2;}
}
$1 ~ /^[-0-9]*(\.[0-9]*)?$/ && NR!=1 {
# setting min value
if (c==0) {min = $1;}
# middle two values in array
if (c==med1_loc) {med1_val = $1;}
if (c==med2_loc) {med2_val = $1;}
c++
sum += $1
max = $1
}
END {
ave = sum / c
median = (med1_val + med2_val ) / 2
print "sum:" sum
print "count:" c
print "mean:" ave
print "median:" median
print "min:" min
print "max:" max
}
'
FILENAME
하고 설정 한 내용을 알기 때문에 코드가 안전 하지만 일반적으로 타당한 이유가없는 한 항상 쉘 변수를 인용해야합니다. 당신이하고있는 일을 알고 있는지 확인하십시오 . (4) 귀하의 답변과 Bruce는 음수 입력을 무시합니다 (즉,로 시작하는 숫자 -
). 질문에 이것이 정확하거나 원하는 행동임을 암시하는 것은 없습니다. 기분 나빠하지 마십시오. 4 년 넘게 지났고, 분명히, 내가 알아 차린 첫 번째 사람입니다.
cat
설명에 추가했습니다.
는 num
작은입니다 awk
정확히 이것과 더 많은, 예를 들면 않습니다 래퍼
$ echo "1 2 3 4 5 6 7 8 9" | num max
9
$ echo "1 2 3 4 5 6 7 8 9" | num min max median mean
..and so on
휴대 성이 뛰어난 awk에서 휠을 재발 명하는 것을 막아줍니다. 위의 문서와 여기에 직접 링크가 있습니다 ( GitHub 페이지 도 확인 하십시오 ).
cat/python
유일한 해결책- 빈 입력 증명이 아닙니다!
cat data | python3 -c "import fileinput as FI,statistics as STAT; i = [int(l) for l in FI.input()]; print('min:', min(i), ' max: ', max(i), ' avg: ', STAT.mean(i), ' median: ', STAT.median(i))"
시원하거나 영리하지 않고 유틸리티에 더 관심이 있다면보다 perl
쉬운 선택 awk
입니다. 대체로 일관된 동작으로 모든 * nix에 있으며, Windows에 쉽고 무료로 설치할 수 있습니다. 나는 또한 그것보다 덜 암호 적이라고 생각하며 awk
, 직접 작성하는 것과 R과 같은 것 사이의 중간 집을 원한다면 사용할 수있는 통계 모듈이있을 것입니다. 내 테스트되지 않은 (실제로 버그가 있지만 내 목적으로는 효과가 있음 ) perl
스크립트는 작성하는 데 약 1 분이 걸렸습니다. 유일한 암호 부분은 while(<>)
매우 유용합니다. 즉, 명령 줄 인수로 전달 된 파일을 가져 와서 한 번에 한 줄씩 읽고 특수 변수의 해당 줄$_
. 따라서 이것을 count.pl이라는 파일에 넣고 다음과 같이 실행할 수 있습니다 perl count.pl myfile
. 그 외에는 무슨 일이 일어나고 있는지 분명하게 알아야합니다.
$max = 0;
while (<>) {
$sum = $sum + $_;
$max = $_ if ($_ > $max);
$count++;
}
$avg=$sum/$count;
print "$count numbers total=$sum max=$max mean=$avg\n";
function median()
{
declare -a nums=($(cat))
printf '%s\n' "${nums[@]}" | sort -n | tail -n $((${#nums[@]} / 2 + 1)) | head -n 1
}
sh
)를 해석기로 사용하고 있다고 말해야합니다 . 파일에서 배열로 데이터를 읽는 방법에도 문제가 있습니다.