Стандартное отклонение нескольких файлов с разными размерами строк

У меня есть несколько файлов с разными размерами строк, но количество столбцов в каждом файле одинаково. например

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    ?       ?

В каждом файле 1-й столбец представляет номер индекса, а 2-й столбец — идентификатор. Я хотел бы рассчитать стандартное отклонение для каждого индекса, начиная с 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      ?       ?

Я пытаюсь изменить следующий скрипт, который работает для средних значений (скопировано из Среднее значение нескольких файлов с разными размерами строк)

{
    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)

person Kay    schedule 07.07.2020    source источник
comment
Я искренне считаю, что если вы хотите, чтобы другие сделали работу за вас, было бы предпочтительнее предложить что-то (например, финансовую поддержку) взамен.   -  person KamilCuk    schedule 11.07.2020
comment
Большое спасибо за ваши такие комментарии. Я сталкиваюсь с трудностями, поэтому задавайте вопросы здесь и ищите ответ. Если stackoverflow хочет денежной поддержки взамен, тоже хорошо. Но я никогда не видел таких вариантов при публикации вопроса.   -  person Kay    schedule 11.07.2020


Ответы (1)


Вам нужно сохранить исходные числа в столбце 3 в NF, чтобы рассчитать стандарт. один из способов, который вы можете попробовать, — объединить их в значения массива (см. 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      ?       ?
person jxc    schedule 11.07.2020