计算bash中基于两列以上的唯一值的数量

  • 本文关键字:唯一 bash 于两列 计算 awk sed
  • 更新时间 :
  • 英文 :


我需要修改下面的代码来处理多个列。

基于bash 中的两列计算唯一值的数量

awk '                  ##Starting awk program from here.
BEGIN{
FS=OFS="t"
}
!found[$0]++{       ##Checking condition if 1st and 2nd column is NOT present in found array then do following.
val[$1]++            ##Creating val with 1st column inex and keep increasing its value here.
}
END{                   ##Starting END block of this progra from here.
for(i in val){       ##Traversing through array val here.
print i,val[i]     ##Printing i and value of val with index i here.
}
}
'  Input_file          ##Mentioning Input_file name here.

统计每个双(所有DIS(的数量的表

patient  sex    DISa  DISb  DISc  DISd   DISe   DISf  DISg  DISh  DISi
patient1 male   550.1 550.5 594.1 594.3  594.8  591   1019  960.1 550.1
patient2 female 041   208   250.2 276.14 426.32 550.1 550.5 558   041  
patient3 female NA    NA    NA    NA     NA     NA    NA    041   NA 

我需要的输出是:

550.1    3
550.5    2
594.1    1
594.3    1
594.8    1
591    1
1019    1
960.1    1
550.1    1
041    3
208    1
250.2    1
276.14    1
426.32    1
558    1

考虑这个awk:

awk -v OFS='t' 'NR > 1 {for (i=3; i<=NF; ++i) if ($i+0 == $i) ++fq[$i]} END {for (i in fq) print i, fq[i]}' file
276.14  1
960.1   1
594.3   1
426.32  1
208 1
041 3
594.8   1
550.1   3
591 1
1019    1
558 1
550.5   2
250.2   1
594.1   1

更可读的形式:

awk -v OFS='t' '
NR > 1 {
for (i=3; i<=NF; ++i)
if ($i+0 == $i)
++fq[$i]
}
END {
for (i in fq)
print i, fq[i]
}' file

$i+0 == $i是用于确保列值为数字的检查。

如果必须保留排序,则需要一个额外的数组b[]来保留遇到的每个数字的顺序,例如

awk '
BEGIN { OFS = "t" }
FNR > 1 { 
for (i=3;i<=NF;i++)
if ($i~/^[0-9]/) { 
if (!($i in a))
b[++n] = $i;
a[$i]++
}
}
END {
for (i=1;i<=n;i++)
print b[i], a[b[i]]
}' file

示例使用/输出

$ awk '
>     BEGIN { OFS = "t" }
>     FNR > 1 {
>         for (i=3;i<=NF;i++)
>             if ($i~/^[0-9]/) {
>                 if (!($i in a))
>                     b[++n] = $i;
>                 a[$i]++
>             }
>     }
>     END {
>         for (i=1;i<=n;i++)
>             print b[i], a[b[i]]
> }' patients
550.1   3
550.5   2
594.1   1
594.3   1
594.8   1
591     1
1019    1
960.1   1
041     3
208     1
250.2   1
276.14  1
426.32  1
558     1

如果您还有其他问题,请告诉我。

从以上两个答案(@anubhava和@David(中获得完整的解决方案,只需在他们的解决方案中添加一点调整(根据所示的OP示例在此处应用整数值检查(,并在此处添加两个解决方案。仅使用所示样品进行书写和测试。

第一个解决方案: 如果订单在输出中无关紧要,请尝试:

awk -v OFS='t' '
NR > 1 {
for (i=3; i<=NF; ++i)
if (int($i))
++fq[$i]
}
END {
for (i in fq)
print i, fq[i]
}' Input_file


第二个解决方案:如果订单根据David的回答很重要,请尝试。

awk '
BEGIN { OFS = "t" }
FNR > 1 { 
for (i=3;i<=NF;i++)
if (int($i)) { 
if (!($i in a))
b[++n] = $i;
a[$i]++
}
}
END {
for (i=1;i<=n;i++)
print b[i], a[b[i]]
}' Input_file

使用GNU awk进行多字符RS:

$ awk -v RS='[[:space:]]+' '$0+0 == $0' file | sort | uniq -c
3 041
1 1019
1 208
1 250.2
1 276.14
1 426.32
3 550.1
2 550.5
1 558
1 591
1 594.1
1 594.3
1 594.8
1 960.1

如果字段的顺序真的很重要,只需将上面的内容传送到awk '{print $2, $1}'即可。

最新更新