我有一个如下所示的文本文件,尽管几乎有很多列。我想提取具有具体比例/数量TRUE 值的数量,例如 9 行中有 2 行包含 TRUE 的列(具有 TRUE/FALSE 值)。
或者,最好提取列至少有一定数量(例如 2)的 TRUE 值。在上面的示例中,列中可能有 2 到 9 行具有 TRUE 值。应该可推广到具有不同行数的文件。
谢谢!
输入文件示例:
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
具有 2 个或更多 TRUE 值的列的所需结果:
输出文件:
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) 具有超过 1 个 TRUE 值:实际上是 3 个。
第 3 列(组 1)有 2 个 TRUE 值。
第 11 列 (group1.8) 有 1 个 TRUE 值。第 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
可以对输出进行 grep 查找“3 of 9”等字符串,以获取列号(从 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
值,则输出列名和百分比。