열의 TRUE 값 비율을 기준으로 TRUE/FALSE 행렬에서 열을 추출합니다.

열의 TRUE 값 비율을 기준으로 TRUE/FALSE 행렬에서 열을 추출합니다.

거의 많은 열이 있지만 아래와 같은 텍스트 파일이 있습니다. 가지고 있는 것을 추출하고 싶다특정 비율/수량TRUE 값의 수. 예를 들어 9개 행 중 2개에는 TRUE 열(TRUE/FALSE 값 포함)이 포함되어 있습니다.

또는 열을 추출하는 것이 더 좋습니다.적어도TRUE 값의 특정 수(예: 2)입니다. 위의 예에서는 열에 TRUE 값이 있는 행이 2~9개 있을 수 있습니다. 다양한 줄 수의 파일로 일반화해야 합니다.

감사해요!

입력 파일 예:

Comparison  MT  group1  group1.1    group1.2    group1.3    group1.4    group1.5    group1.6    group1.7    group1.8    group1.9
BP:HA      FALSE FALSE  FALSE       FALSE       FALSE       FALSE       FALSE       FALSE       FALSE       FALSE        TRUE
CB:HA      FALSE TRUE   FALSE       FALSE       FALSE       FALSE       FALSE       FALSE       FALSE       FALSE        FALSE 
HA:PI      TRUE  TRUE   FALSE       FALSE       FALSE       FALSE       FALSE       FALSE       FALSE       FALSE        FALSE 
AL:GR      FALSE FALSE  FALSE       FALSE       FALSE       FALSE       FALSE       FALSE       FALSE       FALSE        FALSE 
AL:LA      TRUE  FALSE  FALSE       FALSE       FALSE       FALSE       FALSE       FALSE       FALSE       FALSE        FALSE 
AL:PL      FALSE FALSE  FALSE       FALSE       FALSE       FALSE       FALSE       FALSE       FALSE       TRUE         FALSE 
GR:PP      FALSE FALSE  FALSE       FALSE       FALSE       FALSE       FALSE       FALSE       FALSE       FALSE        FALSE 
LA:PP      TRUE  FALSE  FALSE       FALSE       FALSE       FALSE       FALSE       FALSE       FALSE       FALSE        TRUE
PL:PP      FALSE FALSE  FALSE       FALSE       FALSE       FALSE       FALSE       FALSE       FALSE       FALSE        TRUE

TRUE 값이 2개 이상인 열에 대한 원하는 결과:

결과물 파일:

MT
group1
group1.9

답변1

모든 열을 스캔하고 각 열에 대해 "TRUE" 개수를 누적합니다.
마지막으로, 설정점보다 크거나 같은 모든 열을 인쇄합니다.

#!/bin/bash
awk -vprop="${1:-0.3}" '
        NR==1{split($0,fields);next};
        {for(i=2;i<=NF;i++){  if($i=="TRUE" ){t[i]++};
                              if($i=="FALSE"){f[i]++}
                           }
        }
        END{
            for(j in t)
            if( (1/(1+f[j]/t[j])) >= prop){
                printf("%-10s\t%s\t%s\n",fields[j],j,1/(1+f[j]/t[j]) )
            }
        }' infile

실행 시(제공한 데이터에 대해):

$ ./script  0.001
MT              i=2     t=3     f=6     p=0.333
group1          i=3     t=2     f=7     p=0.222
group1.8        i=11    t=1     f=8     p=0.111
group1.9        i=12    t=3     f=6     p=0.333

열 2(MT)에는 TRUE 값이 1개 이상(실제로는 3개) 있습니다.
열 3(그룹 1)에는 TRUE 값이 2개 있습니다.
열 11(group1.8)에는 TRUE 값이 1개 있습니다. 열 12(group1.9)에는 3개의 TRUE 값이 있습니다.

척도를 제공하지 않으면 기본값은 0.3입니다.

$ ./script
MT              i=2     t=3     f=6     p=0.333
group1          i=3     t=2     f=7     p=0.222
group1.9        i=12    t=3     f=6     p=0.333

답변2

bash를 사용하여 충분한 인스턴스가 있는 열을 선택하는 한 가지 방법은 다음과 같습니다 TRUE.

min_true=3; \
max_col=12; \
for col in $(seq 2 $max_col); do \
  sed 's,    ,.,g;s,   ,.,g' "$filename" | \
    tail -n+2 | \
    cut -d. -f$col > /tmp/f; \
  count=$(grep TRUE /tmp/f | wc -l); \
  if [ "$count" -ge "$min_true" ]; then \
    echo "Column $(($col-1)): $count out of $(echo $(wc -l </tmp/f))"; \
    cat /tmp/f; \
  fi; \
done

"3 of 9"와 같은 문자열에 대한 출력을 grep하여 열 번호를 얻을 수 있습니다(0부터 계산 시작).

Column 1: 3 out of 9
FALSE
FALSE
TRUE
FALSE
TRUE
FALSE
FALSE
TRUE
FALSE

답변3

$ awk -v p='10' 'NR==1 { split($0,cols); next }
                 { 
                     for (i=2; i<=NF; ++i)
                         nt[i] += ($i == "TRUE" ? 1 : 0 )
                 }
                 END {
                     for (i=2; i<=NF; ++i) {
                         cp = 100*nt[i]/NR
                         if (cp > p) printf("%-20s %.2f%%\n", cols[i], cp)
                     }
                 }' file
MT                   30.00%
group1               20.00%
group1.9             30.00%

프로그램 awk은 열 헤더를 표시하는 데 필요한 백분율인 하나의 매개변수를 사용합니다 p.TRUE

첫 번째 행부터 시작하여 모든 열 헤더를 배열에 저장합니다 cols. 그런 다음 TRUE해당 단어가 각 열에 나타나는 횟수를 합산합니다 . 마지막으로 TRUE각 열의 행 비율을 계산하고 cp이를 와 비교합니다 p. 주어진 p값보다 큰 경우, 컬럼명과 백분율을 출력합니다.

관련 정보