AWK:多列CSV数据的统计操作
为了对多列数据进行一些统计分析,我正在使用以下bash+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 $
#!/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