AWK:多列CSV数据的统计操作

AWK:多列CSV数据的统计操作,csv,awk,Csv,Awk,为了对多列数据进行一些统计分析,我正在使用以下bash+AWK例程分析大量CSV填充: #!/bin/bash home="$PWD" # folder with the outputs rescore="${home}"/rescore # folder with the folders to analyse storage="${home}"/results #cd "${home}"/results cd $

为了对多列数据进行一些统计分析,我正在使用以下bash+AWK例程分析大量CSV填充:

#!/bin/bash
home="$PWD"
# folder with the outputs
rescore="${home}"/rescore 
# folder with the folders to analyse
storage="${home}"/results
#cd "${home}"/results
cd ${storage}
csv_pattern='*_filt.csv'


while read -r d; do
awk -v rescore="$rescore" '
FNR==1 {
   if (n)
      mean[suffix] = s/n
   prefix=suffix=FILENAME
   sub(/_.*/, "", prefix)
   sub(/\/[^\/]+$/, "", suffix)
   sub(/^.*_/, "", suffix)
   s=n=0
}
FNR > 1 {
   s += $3
   ++n
}
END {
   out = rescore "/" prefix ".csv"
   mean[suffix] = s/n
   print prefix ":", "dG(mean)" > out
   for (i in mean)
      printf "%s: %.2f\n", i, mean[i] >> out
   close(out)
}' "${d}_"*/${csv_pattern} #> "${rescore}/"${d%%_*}".csv"
done < <(find . -maxdepth 1 -type d -name '*_*_*' | awk -F '[_/]' '!seen[$2]++ {print $2}')
向10V1.csv添加1个字符串,该字符串以2列格式组织i)带有初始csv的文件夹后缀的名称;ii)input.csv第三列(dG)中所有数字的计算平均值:

# this is two column format of output.csv: 10V1.csv
10V1: dG(mean)
lig1001: -5.37
这样,对于100个CSV填充,这样的output.CSV应该包含100行平均值,等等

我需要对我的例程的AWK部分进行一个小的修改,将第三列添加到初始数据(dG)的输出CSV中,初始数据(dG)的RMSD值(作为初始dG值之间差异的度量值),用于计算平均值。使用AWK语法,使用特定的平均值,RMS可以表示为

mean=$(awk -F , '{sum+=$3}END{printf "%.2f", sum/NR}' $csv)
rmsd=$(awk -v mean=$mean '{++n;sum+=($NF-mean)^2} END{if(n) printf "%.2f", sqrt(sum/n)}' $csv)
这里是为5个CSV日志计算的5个平均值和5个rmsds值的预期输出(第一个对应于我上面的示例!):


如何将此添加合并到我的主bash AWK代码中,以便将第三个RMSD列(对于每个处理的CSV,从而获取每个计算的平均值)添加到输出.CSV?

您可以在
AWK
代码中计算
平均值和
RMSD

请您尝试以下
awk
code:

awk -v rescore="$rescore" '
FNR==1 {
   if (n) {                     # calculate the results of previous file
      m = s / n                 # mean
      var = s2 / n - m * m      # variance
      if (var < 0) var = 0      # avoid an exception due to round-off error
      mean[suffix] = m          # store the mean in an array
      rmsd[suffix] = sqrt(var)
   }
   prefix=suffix=FILENAME
   sub(/_.*/, "", prefix)
   sub(/\/[^\/]+$/, "", suffix)
   sub(/^.*_/, "", suffix)
   s = 0                        # sum of $3
   s2 = 0                       # sum of $3 ** 2
   n = 0                        # count of samples
}
FNR > 1 {
   s += $3
   s2 += $3 * $3
   ++n
}
END {
   out = rescore "/" prefix ".csv"
   m = s / n
   var = s2 / n - m * m
   if (var < 0) var = 0
   mean[suffix] = m
   rmsd[suffix] = sqrt(var)

   print prefix ":", "dG(mean)", "dG(rmsd)" > out
   for (i in mean)
      printf "%s: %.2f %.2f\n", i, mean[i], rmsd[i] >> out
   close(out)
}' 
  • 我假设所有的
    dG
    值都是负值。如果有机会的话 值大于零,请修改初始化的行
    min=0
    将变量设置为相当大的值(10000或任何值)
  • 如果需要,请应用有关文件名的修改
  • 埃德·莫顿(Ed Morton)的建议也包括在内,尽管结果是一样的

请您在预期输出中显示5个平均值及其相应的
rmsd
值,并作进一步解释好吗?但是为什么
mean=-9.53
具有
rmsd=0
?因为在这种情况下,初始CSV(从中计算平均值)只包含一行,所以在这种情况下没有变量,RMSD=0:-)有一个有价值的答案,我将接受!请参考它,因为它包含RMSD计算的良好解决方案。顺便说一句,我们发现了与AWK部分相关的小错误:在CSV集合中的一个例子中,它将包含后缀的标题放在第二行,如lig1:-7.04 0.20 10V2:dG(mean)dG(rmsd)#它应该始终在output.CSV的第一行!!lig2:-5.79 0.45实际上我不知道为什么:我只是在前缀中添加了一个小后缀“data_uu”,它解决了这个问题:打印“data_uu”前缀,“dG(重新扫描)”,“dG(rmsd)”>谢谢!它工作得很好,但在某个地方有一个错误:在CSV集合的情况下,它将包含后缀的标题放在第二行,如lig1:-7.04 0.20 10V2:dG(mean)dG(rmsd)#它应该始终位于输出.CSV的第一行!!lig2:-5.79 0.45感谢您的反馈。你能提供一组文件名让我重现这个问题吗?实际上,我并不完全理解文件名的结构,因为我认为它可能与rmsd值的计算无关。如果你能自己解决这个问题,一切都没问题。awk对
>
的语义与shell不同<代码>>>out
应该是
>out
(尽管它可以正常工作)。同样,它不会破坏任何东西,但您不需要
关闭(out)
,因为awk会为您这样做。由于在结束部分将其用作除数之前未测试
n
,因此在所有空输入文件上都会出现被零除的错误(在FNR==1等效代码中测试)。您应该将FNR==1中的公共代码放在一个函数中,这样它只定义了一次,但调用了两次。干杯,我想是的。您需要引入另一个将$2值与$3值关联的数组,以与今天类似的方式找到最大$2,然后映射到要打印的关联$3。祝你好运
10V1: dG(mean): RMSD (error)
lig1001 -5.37 0.30
lig1002 -8.53 0.34
lig1003 -6.57 0.25
lig1004 -9.53 0.00 # rmsd=0 since initial csv has only 1 line: no data variance 
lig1005 -8.11 0.39
awk -v rescore="$rescore" '
FNR==1 {
   if (n) {                     # calculate the results of previous file
      m = s / n                 # mean
      var = s2 / n - m * m      # variance
      if (var < 0) var = 0      # avoid an exception due to round-off error
      mean[suffix] = m          # store the mean in an array
      rmsd[suffix] = sqrt(var)
   }
   prefix=suffix=FILENAME
   sub(/_.*/, "", prefix)
   sub(/\/[^\/]+$/, "", suffix)
   sub(/^.*_/, "", suffix)
   s = 0                        # sum of $3
   s2 = 0                       # sum of $3 ** 2
   n = 0                        # count of samples
}
FNR > 1 {
   s += $3
   s2 += $3 * $3
   ++n
}
END {
   out = rescore "/" prefix ".csv"
   m = s / n
   var = s2 / n - m * m
   if (var < 0) var = 0
   mean[suffix] = m
   rmsd[suffix] = sqrt(var)

   print prefix ":", "dG(mean)", "dG(rmsd)" > out
   for (i in mean)
      printf "%s: %.2f %.2f\n", i, mean[i], rmsd[i] >> out
   close(out)
}' 
awk -v rescore="$rescore" '
FNR==1 {
   if (n) {                     # calculate the results of previous file
      m = s / n                 # mean
      var = s2 / n - m * m      # variance
      if (var < 0) var = 0      # avoid an exception due to round-off error
      mean[suffix] = m          # store the mean in an array
      rmsd[suffix] = sqrt(var)
      lowest[suffix] = min
   }
   prefix=suffix=FILENAME
   sub(/_.*/, "", prefix)
   sub(/\/[^\/]+$/, "", suffix)
   sub(/^.*_/, "", suffix)
   s = 0                        # sum of $3
   s2 = 0                       # sum of $3 ** 2
   n = 0                        # count of samples
   min = 0                      # lowest value of $3
}
FNR > 1 {
   s += $3
   s2 += $3 * $3
   ++n
   if ($3 < min) min = $3       # update the lowest value
}
END {
   if (n) {                     # just to avoid division by zero
      m = s / n
      var = s2 / n - m * m
      if (var < 0) var = 0
      mean[suffix] = m
      rmsd[suffix] = sqrt(var)
      lowest[suffix] = min
   }
   out = rescore "/" prefix ".csv"
   print prefix ":", "dG(mean)", "dG(rmsd)", "dG(lowest)" > out
   for (i in mean)
      printf "%s: %.2f %.2f %.2f\n", i, mean[i], rmsd[i], lowest[i] > out
}' file_*.csv