【发布时间】:2014-09-19 07:37:51
【问题描述】:
我有如下所示的数据文件 (data.txt),
0.01667 20.53
0.01667 6.35
0.01667 6.94
0.01667 7.07
0.01667 8.06
0.01667 8.10
0.01667 8.25
0.01667 8.71
0.01667 9.31
0.02500 20.19
0.02500 6.35
0.02500 6.92
0.02500 7.07
0.02500 8.08
0.02500 8.09
0.02500 8.24
0.02500 8.70
0.02500 9.26
0.03333 19.89
0.03333 6.33
0.03333 6.90
0.03333 7.07
0.03333 8.07
0.03333 8.09
0.03333 8.22
0.03333 8.70
0.03333 9.22
0.04167 19.65
0.04167 6.34
0.04167 6.87
0.04167 7.07
0.04167 8.03
0.04167 8.08
0.04167 8.19
0.04167 8.69
0.04167 9.19
0.05000 19.40
0.05000 6.32
0.05000 6.85
0.05000 7.06
0.05000 8.02
0.05000 8.09
0.05000 8.16
0.05000 8.71
0.05000 9.15
0.05833 19.12
0.05833 6.29
0.05833 6.84
0.05833 7.04
0.05833 8.01
0.05833 8.11
0.05833 8.16
0.05833 8.71
0.05833 9.11
0.06667 18.84
0.06667 6.29
0.06667 6.82
0.06667 7.05
0.06667 7.98
0.06667 8.11
0.06667 8.14
0.06667 8.71
0.06667 9.06
0.07500 18.57
0.07500 6.29
0.07500 6.80
0.07500 7.06
0.07500 7.97
0.07500 8.10
0.07500 8.13
0.07500 8.71
0.07500 9.02
第 1 列是第 2 列中进行测量的时间。我需要对第 1 列中给出的每个时间的第 2 列中的值进行平均,并输出该时间的值和该时间的平均值。我可以使用以下 awk 代码进行平均
awk '{if($1<0)$1=0}
{
sum[$1]+=$2
cnt[$1]++
}
END {
# print "Name" "\t" "sum" "\t" "cnt" "\t" "avg"
for (i in sum)
printf "%8.5f %6.2f %6d %6.3f\n", i, sum[i], cnt[i], sum[i]/cnt[i]
}' data.txt | sort -n -k1 > avgFile.txt
请注意,我还输出了一些其他内容,以便我可以检查是否在做正确的事情。正如您所看到的,每个时隙的数据都包含异常值,我需要删除这些。我尝试将在 0.01667 收集的数据选择到某个文件 temp.txt,并且我有以下 awk 代码可以正确删除异常值
awk 'BEGIN{CNT=0} {ROW[CNT]=$0;DATA[CNT]=$2;
TOTAL+=$2;CNT+=1;} END{for (i = 0;i < NR; i++){if ((sqrt((DATA[i]-(TOTAL/NR))^2))<((TOTAL/NR)*30/100))
{print ROW[i] ;}}}' temp.txt
但我需要在原始代码中执行此操作,以便在计算第 2 列中的值的平均值之前,在每次有一个异常值时删除该异常值
我们将不胜感激。
【问题讨论】:
-
您的问题不在于 awk,而在于您需要在读取数据时检测异常值。你会怎么做?将第一个点检测为异常值?这不是微不足道的,参见例如citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.109.1943.
-
感谢您的评论本杰明,在这种情况下,我使用了标准偏差,我认为数据中的一个值与平均值的偏差超过 30%,这是一个异常值,我认为这是有足够的理由从平均计算中删除这样的值。感谢研究的链接,我还不能下载完整的手稿。一旦我有完整的论文,我会阅读它
-
您可以尝试一些简单的方法。就像将特定时间的所有值读入一个数组,对数据进行平均,然后计算每个点的偏差,删除任何大于您提出的某个阈值的点。例如
.01667,平均值为9.25,如果您将阈值设置为4,您将消除异常值。同样的逻辑似乎适用于所有异常值。 -
嗨,大卫,我一直在尝试做类似的事情,正如您在我的第二段代码中看到的那样,我使用的事实是,如果特定值与平均值的偏差超过 30% ,我删除它。我现在面临的问题是如何在我的代码中实现这一点,我既选择特定时间的数据,然后删除异常值,最后计算平均值。我的 awk 技能还处于起步阶段
-
@malandisa 我不是
awk专家,但是一个简单的 bash 脚本可以轻松处理它。只需使用while loop并将值同时添加到 tmp 数组,处理数组以删除异常值,然后获取剩余值的 avg、mean 和 std dev,取消设置数组并移至下一次。如果有机会,我会写一个例子。