任意加权移动平均值(低通和高通滤波器)
arbitrarily weighted moving average (low- and high-pass filters)
给定输入信号x
(例如电压,每秒采样一千次,持续几分钟),我想计算例如
/ this is not q
y[3] = -3*x[0] - x[1] + x[2] + 3*x[3]
y[4] = -3*x[1] - x[2] + x[3] + 3*x[4]
. . .
我的目标是可变 window 长度和重量系数。我怎样才能在q中做到这一点?我知道 mavg and signal processing in q and moving sum qidiom
在 DSP 世界中,它被称为通过卷积来应用滤波器内核。权重系数定义内核,构成高通或低通滤波器。上面的示例计算最后四个点的斜率,通过最小二乘法放置直线。
像这样的东西适用于参数化系数:
q)x:10+sums -1+1000?2f
q)f:{sum x*til[count x]xprev\:y}
q)f[3 1 -1 -3] x
0n 0n 0n -2.385585 1.423811 2.771659 2.065391 -0.951051 -1.323334 -0.8614857 ..
具体情况可以做的快一点(运行 0 xprev 不是最好的)
q)g:{prev[deltas x]+3*x-3 xprev x}
q)g[x]~f[3 1 -1 -3]x
1b
q)\t:100000 f[3 1 1 -3] x
4612
q)\t:100000 g x
1791
如果您对此领域感兴趣,q 中有 kx 信号处理白皮书:https://code.kx.com/q/wp/signal-processing/
如果您的输入列表不大,那么您可以使用这里提到的技术:
https://code.kx.com/q/cookbook/programming-idioms/#how-do-i-apply-a-function-to-a-sequence-sliding-window
那用了'scan'副词。由于该过程会创建多个列表,这对于大列表来说可能效率低下。
使用扫描的其他解决方案是:
q)f:{sum y*next\[z;x]} / x-input list, y-weights, z-window size-1
q)f[x;-3 -1 1 3;3]
此函数还会创建多个列表,因此对于大列表来说可能效率不高。
其他选项是使用索引从输入列表中获取目标项并执行计算。这将仅对输入列表进行操作。
q) f:{[l;w;i]sum w*l i+til 4} / w- weight, l- input list, i-current index
q) f[x;-3 -1 1 3]@'til count x
这是一个非常基本的功能。您可以根据需要向其中添加更多变量。
这可能有点旧,但我想我会权衡一下。我去年写了一篇关于信号处理的论文,可能有一定的价值。纯粹在 KDB 内工作,根据您使用的信号大小,您会发现 kernel/window 和信号之间基于 FFT 的卷积具有更好的性能。
但是,我只写了一个简单的基数 2 FFT,尽管在我的 github 存储库中我确实有未经测试的更灵活的 Bluestein 算法的工作,它将允许更多可变的信号长度。 https://github.com/callumjbiggs/q-signals/blob/master/signal.q
如果您想通过移动求和执行完全手动卷积,那么最好的方法是将其分解成等于 kernel/window 大小的块(基于Arthur W 多年前做过的一些工作)
q)vec:10000?100.0
q)weights:30?1.0
q)wsize:count weights
q)(weights$(((wsize-1)#0.0),vec)til[wsize]+) each til count v
32.5931 75.54583 100.4159 124.0514 105.3138 117.532 179.2236 200.5387 232.168.
给定输入信号x
(例如电压,每秒采样一千次,持续几分钟),我想计算例如
/ this is not q
y[3] = -3*x[0] - x[1] + x[2] + 3*x[3]
y[4] = -3*x[1] - x[2] + x[3] + 3*x[4]
. . .
我的目标是可变 window 长度和重量系数。我怎样才能在q中做到这一点?我知道 mavg and signal processing in q and moving sum qidiom
在 DSP 世界中,它被称为通过卷积来应用滤波器内核。权重系数定义内核,构成高通或低通滤波器。上面的示例计算最后四个点的斜率,通过最小二乘法放置直线。
像这样的东西适用于参数化系数:
q)x:10+sums -1+1000?2f
q)f:{sum x*til[count x]xprev\:y}
q)f[3 1 -1 -3] x
0n 0n 0n -2.385585 1.423811 2.771659 2.065391 -0.951051 -1.323334 -0.8614857 ..
具体情况可以做的快一点(运行 0 xprev 不是最好的)
q)g:{prev[deltas x]+3*x-3 xprev x}
q)g[x]~f[3 1 -1 -3]x
1b
q)\t:100000 f[3 1 1 -3] x
4612
q)\t:100000 g x
1791
如果您对此领域感兴趣,q 中有 kx 信号处理白皮书:https://code.kx.com/q/wp/signal-processing/
如果您的输入列表不大,那么您可以使用这里提到的技术: https://code.kx.com/q/cookbook/programming-idioms/#how-do-i-apply-a-function-to-a-sequence-sliding-window
那用了'scan'副词。由于该过程会创建多个列表,这对于大列表来说可能效率低下。
使用扫描的其他解决方案是:
q)f:{sum y*next\[z;x]} / x-input list, y-weights, z-window size-1
q)f[x;-3 -1 1 3;3]
此函数还会创建多个列表,因此对于大列表来说可能效率不高。
其他选项是使用索引从输入列表中获取目标项并执行计算。这将仅对输入列表进行操作。
q) f:{[l;w;i]sum w*l i+til 4} / w- weight, l- input list, i-current index
q) f[x;-3 -1 1 3]@'til count x
这是一个非常基本的功能。您可以根据需要向其中添加更多变量。
这可能有点旧,但我想我会权衡一下。我去年写了一篇关于信号处理的论文,可能有一定的价值。纯粹在 KDB 内工作,根据您使用的信号大小,您会发现 kernel/window 和信号之间基于 FFT 的卷积具有更好的性能。
但是,我只写了一个简单的基数 2 FFT,尽管在我的 github 存储库中我确实有未经测试的更灵活的 Bluestein 算法的工作,它将允许更多可变的信号长度。 https://github.com/callumjbiggs/q-signals/blob/master/signal.q
如果您想通过移动求和执行完全手动卷积,那么最好的方法是将其分解成等于 kernel/window 大小的块(基于Arthur W 多年前做过的一些工作)
q)vec:10000?100.0
q)weights:30?1.0
q)wsize:count weights
q)(weights$(((wsize-1)#0.0),vec)til[wsize]+) each til count v
32.5931 75.54583 100.4159 124.0514 105.3138 117.532 179.2236 200.5387 232.168.