질문:

질문:

.txt 파일에 있는 특정 열의 중앙값을 계산하고 해당 값을 출력하고 출력 값이 정상인지 확인하고 싶습니다. 초기 단계를 수행하고 중앙값을 출력할 수 있지만 출력값이 허용 범위 내에 있는지 여부를 알 수 없습니다.

다음 코드가 포함된 구문 오류 메시지가 나타납니다.

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"}'

답변1

내 생각엔 이게 네가 원하는 거야

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

비교적 깔끔하게 정리되어 있어요

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

또한 비교에 몇 가지 논리를 추가하고 싶지만 변수가 x, y, z라고 불리며 올바른 방정식이 있을 수도 있고 없을 수도 있기 때문에 무엇을 비교하고 있는지 실제로 알 수 없습니다.

답변2

user78605쿼리에서 중앙값을 찾는 방법을 안내해 주는 코드를 제공해 주셔서 감사합니다 . 그러나 위 코드는 중앙값을 올바르게 계산하는 데 필요한 특정 조건을 무시합니다.

질문:

  1. 빈 후행 행이 파일에 존재하는 경우 이를 계산하면 데이터 크기, 즉 평균, 중앙값, 모드 및 기타 통계에 영향을 미치기 때문에 계산해서는 안 됩니다. 숫자 값이 없는 행(id est: , , "abc""28b") 에 대해서도 동일한 작업을 수행해야 합니다 ."h2f"""
  2. 중앙값은 원래 데이터 세트의 중간 값이 아니라 정렬된 데이터 세트의 중간 값입니다. 즉, 중앙값을 찾으려면 먼저 데이터를 정렬해야 합니다.
  3. 정렬된 데이터 세트의 값 개수가 짝수인 경우에는 가운데 두 값의 평균을 취해야 합니다.
  4. 모드는 주파수가 가장 높은 값입니다. 데이터 세트에는 둘 이상의 모드가 있을 수 있으며, 이 경우 둘 이상의 값이 모드로 나열되어야 합니다.

위의 조건을 고려한 코드 확장은 다음과 같습니다.

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

설명하다:

문제 #1에 대한 해결책:

col=$1#변수에 저장하면 열을 변경하기가 더 쉽습니다.
(col ~ /^-?[0-9]*([.][0-9]+)?$/)#Strings에는 숫자, 마침표(소수 구분 기호) 또는 대시(빼기 기호)만 포함될 수 있습니다. [과학적 표기법만 무시합니다. ]
($0!="")#전체 줄을 비워 둘 수 없습니다.

기준을 충족하는 행에 대해 다음 루프 작업을 수행합니다.

sum+=col# (약어 sum=sum+col.) 모든 값의 합계입니다.
a[x++]=col#각 값은 배열에 저장됩니다.
b[col]++#의 값은 col배열의 대리 키로 처리됩니다 b. 따라서 b에 고유한 값이 있는 만큼 에 많은 요소가 있습니다 col. 이 반복자는 빈도 수의 배열을 생성합니다. (약어 b[col]=b[col]+1.)
if(b[col]>hf){hf=b[col]}# hf"가장 높은 주파수"를 뜻합니다. 모든 주파수를 반복하고 hf더 높은 주파수가 발견된 경우에만 업데이트합니다. hf처음에는 ""(아무것도 없음)입니다.

문제 #2에 대한 해결 방법:
루프 작업이 완료된 후:

배열에 저장된 값을 정렬합니다.n = asort(a)

배열의 원래 인덱스 범위가 a"0"에서 "x-1"까지라는 점은 주목할 가치가 있습니다. 정렬 외에도 새 인덱스 범위는 "1"부터 "x"까지입니다. 그렇기 때문에 중앙값 또는 중앙값의 평균을 계산할 두 숫자 중 더 작은 숫자를 보유하는 인덱스로 int((x+1)/2)대신 사용하고 있습니다.
int((x-1)/2)

문제 #3에 대한 해결책:

((idx == (x+1)/2) ? a[idx] : (a[idx]+a[idx+1])/2)
이것은 if-else 구조에 대한 약칭 표기법입니다. 동일
하면 값의 개수는 홀수이고 중앙값은 입니다 . 그렇지 않은 경우 가장 가까운 정수로 반내림되어 값의 개수가 짝수임을 나타냅니다. 이 경우 합계의 평균이 중앙값이 됩니다.int((x+1)/2)(x+1)/2a[idx]int()(x+1)/2a[idx]a[idx]+1

문제 #4에 대한 해결책:

for (i in b) {if(b[i]==hf){(k=="") ? (k=i):(k=k FS i)}{FS=","}}
hf는 데이터 세트에서 가장 높은 빈도를 나타내는 값이므로 b의 값이 와 같으면 대리 hf키는 모드이거나 모드 중 적어도 하나입니다.
이 코드는 i조건과 일치하는 모든 대리 키를 연결하고 이를 k"Mode"라는 줄에 인쇄할 수 있는 변수에 저장합니다.

추가 조정:

-F파일에서 열 구분 기호로 사용되는 문자를 기준으로 조정해야 합니다.

NR > 1파일의 첫 번째 줄 에 헤더가 있으면 {col=$1}.

FS두 변수를 결합하는 데 사용됩니다. FSUse는 구분 기호를 사용하지 않기로 선택한 경우에 특히 유용합니다. 그건, FS="".

데이터

스크립트를 작성하기 위해 실험에서 다음 데이터가 사용되었습니다.

10
20
10
20.5
50
30
40
50
10
30
20.5


-h
h

4.35
-537
0
-0

30
d




.

결과:

Mean: -13.2281
Median: 20.25
Mode: 10,30

관련 정보