【问题标题】:Standard deviation of multiple files having different row sizes具有不同行大小的多个文件的标准差
【发布时间】:2020-07-07 15:20:28
【问题描述】:

我有几个行大小不同的文件,但每个文件中的列数是相同的。例如

ifile1.txt

1       1001    ?       ?
2       1002    ?       ?
3       1003    ?       ?
4       1004    ?       ?
5       1005    ?       0
6       1006    ?       1
7       1007    ?       3
8       1008    5       4
9       1009    3       11
10      1010    2       9

ifile2.txt

1       2001    ?       ?
2       2002    ?       ?
3       2003    ?       ?
4       2004    ?       ?
5       2005    ?       0
6       2006    6       12
7       2007    6       5
8       2008    9       10
9       2009    3       12
10      2010    5       7
11      2011    2       ?
12      2012    9       ?

ifile3.txt

1       3001    ?       ?
2       3002    ?       6
3       3003    ?       ?
4       3004    ?       ?
5       3005    ?       0
6       3006    1       25
7       3007    2       3
8       3008    ?       ?

在每个文件中,第一列表示索引号,第二列表示 ID。 我想从第 3 列开始计算每个索引号的标准差。

想要的输出:

1       ?       ?          ----  [Here ? is computed from ?, ?, ?] So answer is ?
2       ?       ?          ----  [Here 6 is computed from ?, ?, 6] So answer is ? as only one sample
3       ?       ?
4       ?       ?
5       ?       0.00       ----- [Here 0 is computed from 0, 0, 0] So answer is as all are same value
6       3.54    12.01
7       2.83    1.15
8       2.83    4.24       ----- [Here 7 is computed from 5, 9, ?]
9       0.00    0.71
10      2.12    1.41
11      ?       ?
12      ?       ?

我正在尝试更改以下适用于平均值的脚本(复制自 Average of multiple files having different row sizes

{
    c = NF
    if (r<FNR) r = FNR
    
    for (i=3;i<=NF;i++) {
        if ($i != "?") {
            s[FNR "," i] += $i
            n[FNR "," i] += 1
        }
    }
}

END {
    for (i=1;i<=r;i++) {
        printf("%s\t", i)
        for (j=3;j<=c;j++) {
            if (n[i "," j]) {
                printf("%.1f\t", s[i "," j]/n[i "," j])
            } else {
                printf("?\t")
            }
        }
        printf("\n")
    }
}

  

我了解我需要使用以下内容修改脚本,但无法这样做。

          mean=s[i "," j]/n[i "," j]
          for (i=1; i in array ; i++)
            sqdif+=(array[i]-mean)**2
             printf("%.1f\t", sqdif/(n[i "," j]-1)**0.5)

【问题讨论】:

  • 我真诚地相信,如果您希望其他人为您完成工作,最好提供一些东西(如财务支持)作为交换。
  • 非常感谢你们这样的 cmets。我遇到困难,所以在这里发布问题并寻找答案。如果 stackoverflow 想要金钱支持作为交换,那么也可以。但我在发布问题时从未见过任何此类选项。

标签: shell awk standard-deviation


【解决方案1】:

您需要将第 3 列的原始数字保存到 NF 以计算 std。您可以尝试的一种方法是将它们连接到数组值中(请参阅下面代码中的v),然后在 END 块的最终计算中进行拆分以检索它们,例如:

$ cat test.awk

{
  nMax = FNR > nMax ? FNR : nMax                        # get the max FNR from all files
  for (j=3; j<=NF; j++) {
    if ($j == "?") continue
    v[FNR, j] = v[FNR, j] == "" ? $j : v[FNR, j] FS $j  # concatenate values of (FNR,j) in `v` using FS
    t[FNR, j] += $j                                     # calculate total for each (FNR,j)
  }
}
END {
  for (i=1; i<=nMax; i++) {
    printf("%d\t", i)
    for (j=3; j<=NF; j++) {
      if ((i,j) in t) {         # if (i,j) exists, split v into vals using default FS
        n = split(v[i,j], vals)
        if (n == 1) {           # print "?" if only 1 item in array vals
          printf("?")
        } else {                # otherwise, calculate mean `e`, sum `s` and then std
          e = t[i,j]/n
          s = 0
          for(x in vals) s += (vals[x]-e)**2
          printf("%.2f", sqrt(s/(n-1)))
        }
      } else { # print "?" if (i,j) not exists
        printf("?")
      }
      printf(j==NF?"\n":"\t")
    }
  }
}

以上代码运行结果:

$ awk -f test.awk ifile*.txt
1       ?       ?
2       ?       ?
3       ?       ?
4       ?       ?
5       ?       0.00
6       3.54    12.01
7       2.83    1.15
8       2.83    4.24
9       0.00    0.71
10      2.12    1.41
11      ?       ?
12      ?       ?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-09-11
    • 2019-10-16
    • 2023-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多