列の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)にはTR​​UE値が1つ以上(実際には3つ)あります。
列3(グループ1)にはTR​​UE値が2つあります。
列11(group1.8)にはTR​​UE値が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を使用して十分なインスタンスを持つ列を選択する1つの方法は次のとおりです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は、列ヘッダーを表示するために必要な割合である1つのパラメーターを使用しますpTRUE

最初の行から始めて、すべての列ヘッダーを配列に保存しますcols。次に、TRUEその単語が各列に表示される回数を合計します。最後に、TRUE各列の行の割合を計算し、cpそれをと比較しますp。与えられたp値より大きい場合、列名とパーセンテージを出力します。

関連情報