【问题标题】:calculating average values in a file using awk from multiple files使用来自多个文件的 awk 计算文件中的平均值
【发布时间】:2018-03-01 05:13:42
【问题描述】:

我有 100 个名为 file.1.netcc、file.2.netcc ... file.100.netcc 的文件。每个文件包含以下内容:

# 4 # Number of network ROIs 
# 2 # Number of netcc matrices 
# WITH_ROI_LABELS 
LFovea_LO LLO LMT RV3A 
1 2 3 4 
# CC 
1.0000  0.2271  -0.1172 -0.2258 
0.2271  1.0000  0.3991  0.1092 
-0.1172 0.3991  1.0000  0.3055 
-0.2258 0.1092  0.3055  1.0000 
# FZ 
4.0000  0.2312  -0.1177 -0.2297 
0.2312  4.0000  0.4226  0.1096 
-0.1177 0.4226  4.0000  0.3156 
-0.2297 0.1096  0.3156  4.0000 

现在,例如,我想要平均所有“cc”值。每个值将从所有文件中取平均值。例如,我们取第一列第一行的第一个值(1.0000)从所有文件中取平均值,然后输出为平均值……以此类推,直到最后一位,即第 4 列第 4 行值(1.0000) 对所有文件进行平均。
所以我想要返回的是一个 4x4 表,其中的值是所有文件的平均值。 我也希望为它下面的“FZ”类别完成此操作。我该怎么做?

我尝试使用这个命令:

awk '{a[FNR]+="  "$1"  "$2"  "$3"   "$4"  "$5"  "$6"   "$7"   "$8;b[FNR]++;}END{for(i=1;i<=FNR;i++)print i,a[i]/b[i];}' /Users/3dnetcorr/file*.netcc > outputs_averaged.file

但是这个命令所做的(我认为)是对整个列进行平均,每列给我一个值。这不是我想要的。

我想我要问的是如何平均出包含矩阵的文件? 如何使用 python 编码做到这一点? numpy 可能吗?

【问题讨论】:

  • @melpomene 这是一个错字。它已被修复。我的意思是第四行第四列。
  • 我不会用 awk 做这个。我可能会写一个 perl 程序。

标签: python bash matrix average


【解决方案1】:

awk 来救援!

awk 'FNR==1 {fc++; cc_f==fz_f=0; cc_c=fz_c=0}
    /^# CC/ {cc_f=1; fz_f=0; next}
    /^# FZ/ {cc_f=0; fz_f=1; next}
    cc_f    {cc_c++; for(i=1;i<=NF;i++) cc[cc_c,i]+=$i}
    fz_f    {fz_c++; for(i=1;i<=NF;i++) fz[fz_c,i]+=$i}
    END {print "CC averages"
         for(i=1;i<=cc_c;i++)
           for(j=1;j<=NF;j++) printf "%.4f%s", cc[i,j]/fc, (j==NF?ORS:OFS)
         print "FZ averages"
         for(i=1;i<=fz_c;i++)
           for(j=1;j<=NF;j++) printf "%.4f%s", fz[i,j]/fc, (j==NF?ORS:OFS)}' file{1..100}

这不会验证文件格式,因此应该在文件之间保持一致。 它不假设方阵。一些命名约定 _f 用于标志/指示器 _c 用于计数器。 fc 是文件计数器。您可以结合使用标志和计数器,但会更难解释。

【讨论】:

  • 太好了,谢谢!我应该用 bash 编写这段代码吗?另外,这会打印到新文件吗?
  • 作为bash 脚本,这将非常长、脆弱且毫无意义。如果您已经拥有awk 为什么不使用它。在末尾添加重定向 &gt; outputfile 以将输出发送到文件而不是标准输出。
  • 输出看起来像这样:CC averages 1.00000000 0.17263182 0.10410909 0.13875455 0.11106818 0.17263182 0.77272727 0.22058182 0.12345000 0.06792727 0.10410909 0.22058182 0.54545455 0.16238636 0.02765455 0.13875455 0.12345000 0.16238636 0.40909091 0.04199091 0.11106818 0.06792727 0.02765455 0.04199091 0.27272727 这是错误的,因为对角线不等于一。所有文件,对角线值等于一。因此,在获得平均值时,它应该仍然等于 1。
  • 这很奇怪,任何坐标之间都不应该有任何差异。也许需要添加格式验证。您可以使用 2 或 3 个可以验证输入的文件进行测试吗?
【解决方案2】:

使用 gnu awk

适用于具有# XX 格式的多个矩阵

$ awk '/^# .. $/{key=$2; i=1; PROCINFO["sorted_in"]="@ind_num_asc"; next} 
      !i~/0/ && ARGIND<=100{for(j=1; j<=4; j++) a[key FS i FS j]+=$j; (i>=4)?i=0:i++} 
     END{ 
          for(INDEX in a) { 
            split(INDEX,k,FS); 
            if(!seen[k[1]]++) print "# "k[1]; 
            printf a[k[1] FS k[2] FS k[3]]/(ARGIND)"" (k[3]%4?FS:RS) 
          }
        }' file{1..100}

# CC
8.66667 0.2271 -0.1172 -0.2258
0.2271 1 0.3991 0.1092
-0.1172 4.06577 1 0.3055
-0.2258 0.1092 0.3055 1
# FZ
4 0.2312 -0.1177 -0.2297
0.2312 4 0.4226 0.1096
-0.1177 0.4226 4 0.3156
-0.2297 0.1096 0.3156 4

/^# .. $/ :与# CC# FX# RZ 匹配(注意末尾的空格)。您可以根据需要修改模式。如果匹配此模式,则将键设置为$2key=CCkey=FX

PROCINFO["sorted_in"]="@ind_num_asc":根据键对关联数组a进行排序。排序后的顺序会在遍历过程中反映出来。

ARGIND&lt;=100{...}:这个块总结了每个文件的数组元素。将 100 更改为您想要播放的任意数量的文件

END {..} 块:遍历数组并打印每个元素的平均值。 ARGIND 在这里表示文件数,因此表示每个索引的矩阵元素总数。

【讨论】:

  • @hsayya:这里的输出是基于一些修改后的输入。你能试着告诉我它是否给你想要的输出吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-07-19
  • 1970-01-01
  • 1970-01-01
  • 2014-09-06
  • 2022-01-24
  • 2019-08-01
  • 1970-01-01
相关资源
最近更新 更多