Awk 读取移动平均线前几行中的字段 主要问题

Awk 读取移动平均线前几行中的字段 主要问题,awk,moving-average,Awk,Moving Average,在另一个AWK程序中递归调用AWK,然后将输出保存为(数值)变量的正确语法是什么 我想使用2/3变量调用AWK: N->可以从Bash或容器AWK脚本中读取 Linenum->从容器AWK程序读取 J->我想读的字段 这是我的尝试 集装箱AWk计划: BEGIN {} { ... # Loop in j ... k=NR # Call to other instance of AWK var=(awk -f -v n="$n_steps" linenum=k input-file 'l

在另一个AWK程序中递归调用AWK,然后将输出保存为(数值)变量的正确语法是什么

我想使用2/3变量调用AWK:

  • N->可以从Bash或容器AWK脚本中读取
  • Linenum->从容器AWK程序读取
  • J->我想读的字段
这是我的尝试

集装箱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, 其中kn是最后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
        }
    }
}
我确信这个代码不可能是正确的

讨论问题 获取AWK正在处理的前一行字段信息的最佳方法是什么?然后可以将其保存到变量中吗

是否允许或甚至建议递归使用AWK

如果没有,那么更新累积和值的最有效方法是什么,以便获得足够有效的代码

样本输入和输出 下面是输入(第二列)和所需输出(第三列)的示例。我用3作为平均步数(n)


如果要对单个列进行运行平均,可以通过以下方式进行:

BEGIN{n=2280; c=7}
{ s += $c - a[NR%n]; a[NR%n] = $c }
{ print $0, s /(NR < n : NR ? n) }
但是,您提到您必须添加数百万个条目。这就是它变得有点棘手的地方。当你一点一点地降低精度时(当你添加浮点数时),对很多值求和会引入数值错误。因此,在这种情况下,我建议实施

对于单个列,您可以得到:

BEGIN{n=2280; c=7}
{ y = $c - a[NR%n] - k; t = s + y; k = (t - s) - y; s = t; a[NR%n] = $c }
{ print $0, s /(NR < n : NR ? n) }
BEGIN{n=2280;c=7}
{y=$c-a[NR%n]-k;t=s+y;k=(t-s)-y;s=t;a[NR%n]=$c}
{打印$0,s/(NR
或者进一步扩展为:

BEGIN{n=2280; c=7}
{ y = $c       - k; t = s + y; k = (t - s) - y; s = t; }
{ y = -a[NR%n] - k; t = s + y; k = (t - s) - y; s = t; }
{ a[NR%n] = $c }
{ print $0, s /(NR < n : NR ? n) }
BEGIN{n=2280;c=7}
{y=$c-k;t=s+y;k=(t-s)-y;s=t;}
{y=-a[NR%n]-k;t=s+y;k=(t-s)-y;s=t;}
{a[NR%n]=$c}
{打印$0,s/(NR

对于多列问题,现在可以直接调整上述脚本。您需要知道的是,
y
t
是临时值,
k
是需要存储在内存中的补偿项。

请不要将数据作为图像发布。我们不能用它们来测试。我在这里支持James先生,试着发布3个简单的东西。第一:输入文件的样本,第二个预期输出的样本,第三件事:为您的努力提供的代码样本。尝试对所有代码和示例使用代码标记。获取AWK正在处理的前一行字段信息的最佳方法是什么?然后可以将其保存到变量中吗?它可以保存到变量中,这是最好的方法。例如:
echo-e1\\n2\\n3 | awk'{print$1,p;p=$1}END{print$1,p}'
感谢您的反馈。我添加了文本形式的数据,而不是图像形式的数据。我还将对代码进行注释。我目前正在Windows上工作,因此代码示例可能需要等待,直到我有权访问linux shell。此问题超出了需要。谢谢您的回答!我对AWK还是很陌生,所以给我几分钟的时间来浏览代码,了解正在做什么。太棒了!这真的很有希望。我可能会切换到这个实现。在按答案打分之前,我有两个后续问题:1。就计算效率和资源而言,这种方法是否比再次递归调用AWK以获得所需的值更好(如果可能的话)?2.使用2280步*30列的[]数组时,性能(速度和内存使用)损失是否会明显?我想知道的是,这个数组大小是否可以被大多数计算机忽略(易于管理)。如果是这样的话,我将坚持你建议的方法。回答你的问题:(1)是的,这非常有效,从效率的角度来看,递归调用awk是非常糟糕的,因为在每一步你都会重新打开文件,完全处理它。你会一次又一次地这样做。它会使系统减速一个我不知道有多大的因素。你也将使你的程序以O(n^2)的形式运行,而我在这里介绍的是线性的。这么快就好了。(2)明智的资源将是好的。在第一种情况下,您只需要记住2280*30个浮点数,即只有535kb的内存。不太可能。对于Kahan求和,你需要记住数组+求和+补偿,它保持在535kb左右。所以没什么好担心的。除了(1)因为你把东西存储在内存中,程序不需要重新处理ascii字符串和提取数字(这是一些计算工作),因为你已经把它们放在一个数组中,计算机知道它要处理什么。
BEGIN{n=2280; c[0]=7; c[1]=8; c[2]=9}
{ for(i in c) { s[i] += $c[i] - a[n*i + NR%n]; a[n*i + NR%n] = $c[i] } }
{ printf $0
  for(i=0;i<length(c);++i) printf OFS (s[i]/(NR < n : NR ? n))
  printf ORS
}
BEGIN{n=2280; c=7}
{ y = $c - a[NR%n] - k; t = s + y; k = (t - s) - y; s = t; a[NR%n] = $c }
{ print $0, s /(NR < n : NR ? n) }
BEGIN{n=2280; c=7}
{ y = $c       - k; t = s + y; k = (t - s) - y; s = t; }
{ y = -a[NR%n] - k; t = s + y; k = (t - s) - y; s = t; }
{ a[NR%n] = $c }
{ print $0, s /(NR < n : NR ? n) }