我想计算第2列的总和和15个文件中所有其他列的平均值: - ifile1.txt,ifile2.txt,.....,ifile15.txt。每个文件的列数和行数相同。但其中一些缺少价值观。部分数据显示为
ifile1.txt ifile2.txt ifile3.txt
3 ? ? ? . 1 2 1 3 . 4 ? ? ? .
1 ? ? ? . 1 ? ? ? . 5 ? ? ? .
4 6 5 2 . 2 5 5 1 . 3 4 3 1 .
5 5 7 1 . 0 0 1 1 . 4 3 4 0 .
. . . . . . . . . . . . . . .
我想找到一个新文件,它将显示第2列的总和以及这15个文件中所有其他列的平均值,而不考虑缺失值。
ofile.txt
2.66 2 1 3 . (i.e. average of 3 1 4, sum of ? 2 ?, average of ? 1 ?, average of ? 3 ?, and so on)
2.33 ? ? ? .
3 15 4.33 1.33 .
3 8 4 0.66 .
. . . . .
此问题类似于我之前的问题Average of multiple files without considering missing values,其中脚本是针对所有列的平均值编写的。
awk '
{
for (i = 1;i <= NF;i++) {
Sum[FNR,i]+=$i
Count[FNR,i]+=$i!="?"
}
}
END {
for( i = 1; i <= FNR; i++){
for( j = 1; j <= NF; j++) printf "%s ", Count[i,j] != 0 ? Sum[i,j]/Count[i,j] : "?"
print ""
}
}
' ifile*
但我无法将其修改为我的欲望输出。
答案 0 :(得分:1)
根据您之前的awk
脚本,我将其修改为
$ cat awk_script
{
for (i = 1;i <= NF;i++) {
Sum[FNR,i]+=$i
Count[FNR,i]+=$i!="?"
}
}
END {
for( i = 1; i <= FNR; i++){
for( j = 1; j <= NF; j++)
if(j==2) { printf "%s\t" ,Count[i,j] != 0 ? Sum[i,j] : "?" }
else {
if (Count[i,j] != 0){
val=Sum[i,j]/Count[i,j]
printf "%s%s\t",int(val),match(val,/\.[0-9]/)!=0 ? "."substr(val,RSTART+1,2):""
} else printf "?\t"
}
print ""
}
}
输出结果为:
$ awk -f awk_script ifile*
2.66 2 1 3 0
2.33 ? ? ? 0
3 15 4.33 1.33 0
3 8 4 0.66 0
0 0 0 0 0
简要说明,
if(j==2)
:打印每个文件中值的总和substr(val,RSTART+1,2)
提取小数部分,使用int(val)
提取整数部分答案 1 :(得分:1)
$ cat tst.awk
BEGIN { dfltVal="?"; OFS="\t" }
{
for (colNr=1; colNr<=NF; colNr++) {
if ($colNr != dfltVal) {
sum[FNR,colNr] += $colNr
cnt[FNR,colNr]++
}
}
}
END {
for (rowNr=1; rowNr<=FNR; rowNr++) {
for (colNr=1; colNr<=NF; colNr++) {
val = dfltVal
if ( cnt[rowNr,colNr] != 0 ) {
val = int(100 * sum[rowNr,colNr] / (colNr==2 ? 1 : cnt[rowNr,colNr])) / 100
}
printf "%s%s", val, (colNr<NF ? OFS : ORS)
}
}
}
$ awk -f tst.awk file1 file2 file3
2.66 2 1 3
2.33 ? ? ?
3 15 4.33 1.33
3 8 4 0.66