主要问题
在另一个AWK程序中递归调用AWK,然后将输出保存到(数字)变量的正确语法是什么?
我想用2/3变量调用AWK:
-
N - >可以从Bash或容器AWK脚本中读取 .
-
Linenum - >从容器AWK程序中读取
-
J - >我想阅读的字段
这是我的尝试 .
Container AWk计划:
BEGIN {}
{
...
# Loop in j
...
k=NR
# Call to other instance of AWK
var=(awk -f -v n="$n_steps" linenum=k input-file 'linenum-n {printf "%5.4E", $j}'
...
}
END{}
更一般性问题的背景:
我有一个文件,我想计算n的移动平均值(例如2280) .
-
理想情况下,对于前n行,平均值为1到k,其中k <= n .
-
对于行k> n,平均值将是最后n个值 .
我最终将在许多大型文件中执行代码,包含多个列,以及数千到数百万行,因此我对尽可能简化代码感兴趣 .
代码摘录和说明
我正在尝试开发的代码看起来像这样:
NR>1
{
# Loop over fields
for (j in columns)
{
# Rows before full moving average is done
if ( $1 <= n )
{
cumsum[j]=cumsum[j]+$j #Cumulative sum
$j=cumsum[j]/$1 # Average
}
#moving average
if ( $1 > n )
{
k=NR
last[j]=(awk -f -v n="$n_steps" ln=k input-file 'ln-n {printf "%5.4E", $j}') # Obtain value that will get ubstracted from moving average
cumsum[j]=cumsum[j]+$j-last[j] # Cumulative sum adds last step and deleted unwanted value
$j=cumsum[j]/n # Moving average
}
}
}
我的输入文件包含多个列 . 第一列包含行号,其他列包含值 .
对于移动平均线的累积和:如果我在行k中,我想将它添加到累积和,但也开始减去我不需要的第一个值(k-n) .
我不想为最后的步骤创建一个累积总和数组,因为我觉得它可能会影响性能 . 我更喜欢直接选择我想要减去的值 .
为此,我需要再次呼叫AWK(但在另一条线路上) . 我尝试在这一行中做到这一点:
k=NR
last[j]=(awk -f -v n="$n_steps" ln=k input-file 'ln-n {printf "%5.4E", $j}'
我确信这段代码不正确 .
讨论问题
获取有关AWK正在进行的前一行中某个字段的信息的最佳方法是什么?它可以保存到变量中吗?
是否允许甚至推荐使用AWK的递归使用?
如果没有,那么更新累积和值的最有效方法是什么,以便我获得足够有效的代码?
样本输入和输出
以下是输入(第二列)和所需输出(第三列)的示例 . 我用3作为平均步数(n)
N VAL AVG_VAL
1 1 1
2 2 1.5
3 3 2
4 4 3
5 5 4
6 6 5
7 7 6
8 8 7
9 9 8
10 10 9
11 11 10
12 12 11
13 13 12
14 14 13
14 15 14
1 回答
如果要执行单个列的运行平均值,可以这样做:
这里我们将最后的
n
值存储在数组a
中并跟踪累积和s
. 每当我们更新总和时,我们首先从中删除最后一个值 .如果你想为几列做这个,你必须有点跟踪你的数组
但是,您提到必须添加数百万条目 . 这就是它变得有点棘手的地方 . 总结很多值会导致数字错误,因为你逐渐失去精度(当你添加浮点数时) . 所以在这种情况下,我建议实施Kahan summation .
对于单个列,您将获得:
或者更多扩展为:
对于多列问题,现在可以直接调整上述脚本 . 您需要知道的是
y
和t
是临时值,k
是需要存储在内存中的补偿项 .