打印每列计数以及 header 名称
Print each column count alongwith header name
我有一个昏迷去血文件。我有兴趣用 header 名称计算每列中的行数(列 count/length)。
示例数据集:
ID、IB、IM、IZ
0.05、0.02、0.01、0.09
0.06, 0.01, , 0.08
0.02, 0.06,
列ID:3
列IB:3
IM 列:1
列IZ:2
我试过几个选项:
我可以将这些列拆分成单独的文件,然后可以使用 wc -l File_name 命令计算每个文件中的行数。
这个和我感兴趣的很接近,但还是无法得到header名字。任何帮助将不胜感激。
使用 GNU awk
:
awk -F'[[:space:]]*,[[:space:]]*' 'NR == 1 {header = [=10=]; next} \
{for(i = 1; i <= NF; i++) n[i] += ($i ~ /\S/)} \
END {[=10=] = header; for(i = 1; i <= NF; i++) print "Column " $i ": " n[i]}' file
Column ID: 3
Column IB: 3
Column IM: 2
Column IZ: 1
我会按照以下方式使用 GNU AWK
完成此任务,令 file.txt
内容为
ID, IB, IM, IZ
0.05, 0.02, 0.01, 0.09
0.06, 0.01, , 0.08
0.02, 0.06,
然后
awk 'BEGIN{FS=","}NR==1{split([=11=],names);next}{for(i=1;i<=NF;i+=1){counts[i]+=$i~/[^[:space:]]/}}END{for(i=1;i<=length(names);i+=1){print "Column",names[i]": "counts[i]}}' file.txt
输出
Column ID: 3
Column IB: 3
Column IM: 1
Column IZ: 2
说明:我告诉GNU AWK
,
是字段分隔符,当处理第一条记录时将整行([=17=]
)拆分成数组names
,所以ID
变成 names[1]
, IB
变成 names[2]
, IM
变成 names[3]
等等。完成后转到 next
行。对于除第一行以外的所有列,使用 for
循环迭代列,对于每一行增加 counts[i]
的值(其中 i
是列数) 该列是否包含 non-whitespace character? 即 0
为 false,1
为 true。换句话说,如果 non-whitespace 找到的字符增加 1,否则增加 0。处理完所有行后,遍历 names
并打印具有相应值 counts
的名称。
(在 gawk 4.2.1 中测试)
在每个 Unix 机器上的任何 shell 中使用任何 awk:
$ cat tst.awk
BEGIN { FS=" *, *" }
NR == 1 {
numCols = split([=10=],tags)
next
}
{
for ( i=1; i<=NF; i++ ) {
if ( $i ~ /./ ) {
cnt[i]++
}
}
}
END {
for ( i=1; i<=numCols; i++ ) {
printf "Column %s:%d\n", tags[i], cnt[i]
}
}
$ awk -f tst.awk file
Column ID:3
Column IB:3
Column IM:1
Column IZ:2
我有一个昏迷去血文件。我有兴趣用 header 名称计算每列中的行数(列 count/length)。
示例数据集:
ID、IB、IM、IZ
0.05、0.02、0.01、0.09
0.06, 0.01, , 0.08
0.02, 0.06,
列ID:3
列IB:3
IM 列:1
列IZ:2
我试过几个选项:
我可以将这些列拆分成单独的文件,然后可以使用 wc -l File_name 命令计算每个文件中的行数。
这个
使用 GNU awk
:
awk -F'[[:space:]]*,[[:space:]]*' 'NR == 1 {header = [=10=]; next} \
{for(i = 1; i <= NF; i++) n[i] += ($i ~ /\S/)} \
END {[=10=] = header; for(i = 1; i <= NF; i++) print "Column " $i ": " n[i]}' file
Column ID: 3
Column IB: 3
Column IM: 2
Column IZ: 1
我会按照以下方式使用 GNU AWK
完成此任务,令 file.txt
内容为
ID, IB, IM, IZ
0.05, 0.02, 0.01, 0.09
0.06, 0.01, , 0.08
0.02, 0.06,
然后
awk 'BEGIN{FS=","}NR==1{split([=11=],names);next}{for(i=1;i<=NF;i+=1){counts[i]+=$i~/[^[:space:]]/}}END{for(i=1;i<=length(names);i+=1){print "Column",names[i]": "counts[i]}}' file.txt
输出
Column ID: 3
Column IB: 3
Column IM: 1
Column IZ: 2
说明:我告诉GNU AWK
,
是字段分隔符,当处理第一条记录时将整行([=17=]
)拆分成数组names
,所以ID
变成 names[1]
, IB
变成 names[2]
, IM
变成 names[3]
等等。完成后转到 next
行。对于除第一行以外的所有列,使用 for
循环迭代列,对于每一行增加 counts[i]
的值(其中 i
是列数) 该列是否包含 non-whitespace character? 即 0
为 false,1
为 true。换句话说,如果 non-whitespace 找到的字符增加 1,否则增加 0。处理完所有行后,遍历 names
并打印具有相应值 counts
的名称。
(在 gawk 4.2.1 中测试)
在每个 Unix 机器上的任何 shell 中使用任何 awk:
$ cat tst.awk
BEGIN { FS=" *, *" }
NR == 1 {
numCols = split([=10=],tags)
next
}
{
for ( i=1; i<=NF; i++ ) {
if ( $i ~ /./ ) {
cnt[i]++
}
}
}
END {
for ( i=1; i<=numCols; i++ ) {
printf "Column %s:%d\n", tags[i], cnt[i]
}
}
$ awk -f tst.awk file
Column ID:3
Column IB:3
Column IM:1
Column IZ:2