尝试按均值聚合,然后根据 kdb 中的均值 trim 观察异常值

Trying to aggregate by mean and then trim outliers of observations based on the mean in kdb

我正在尝试按项目类型查找平均值,然后设置一个采用该值的变量 y:

  1. 如果 x = 0,则缺少值,
  2. y = x。然后舍入太大或太小的值:
  3. 如果 x > 0, x > mu, 则设 y = mu
  4. 如果 x < 0, x < mu, 则设 y = mu

这是我试过的方法,没有产生下面想要的结果:

 tab2:([]items:`a`b`a`a`b; x:-6 8 0 -3 5)
 tabsum: select mu:avg x by items from tab2;
 tab2: update y:x from tab2
 tab2: update y:mu from tab2 where x > 0 and x > mu / get error after running above step
 tab2: update y:mu from tab2 where x < 0 and x <= mu

想要的结果:

 items  x   mu    y
     a -6 -3.0 -3.0
     b  8  6.5  6.5
     a  0 -3.0  NaN
     a -3 -3.0 -3.0
     b  5  6.5  5

与此数据相关:

i) NaN 是 kdb 中缺失值的合适类型吗? (例如,NA 与 R 中的 NaNNULL 不同)。根据我目前阅读的内容,我猜是这样。

ii) 是否有更有效的代码来获取 tab2 中的 mu 列?制作另一个 table 并合并我猜效率不高(仍在学习 kdb 的基础知识)

三) 如果我只是 运行

tab2:([]items:`a`b`a`a`b; x:-6 8 0 -3 5)
     tabsum: select mu:avg x by items from tab2;
     tab2: update y:mu from tab2 where x > 0 and x > mu

我得到:

  items  x   mu   y
1     a -6 -3.0 NaN
2     b  8  6.5 6.5
3     a  0 -3.0 NaN
4     a -3 -3.0 NaN
5     b  5  6.5 6.5

第 5 行对我来说没有意义。如果 x < mu,为什么 y = 6.5?我希望该行的 y = 5。显然我对发生的事情的理解是错误的。

iv) 我怎样才能得到想要的结果(我发布的代码不能正常工作)

这可能不是最完美的解决方案,但似乎符合您的标准。我正在使用向量条件 ? 来设置 y:

的值
q)show tab3: update y:?[((x>0) and x>mu) or ((x<0) and x<=mu);mu;x] from update mu:avg x by items from tab2
items x  mu  y  
----------------
a     -6 -3  -3 
b     8  6.5 6.5
a     0  -3  0  
a     -3 -3  -3 
b     5  6.5 5

然后将任何 y=0 值替换为 null 0n(而不是 NaN):

q)update y:0n from tab3 where y=0
items x  mu  y  
----------------
a     -6 -3  -3 
b     8  6.5 6.5
a     0  -3     
a     -3 -3  -3 
b     5  6.5 5

最后一行的意外结果归结为执行顺序; q 代码从右到左执行。所以:

5>0 and 5>6.5

实际意思是:

5>(0 and 5>6.5)

即:

5>0

计算结果为真。要进行所需的比较,您需要使用括号:

q)(5>0) and 5>6.5
0b

您的代码块不起作用有几个原因。在第 2 行,您没有使用 mu 列更新 tab2;您只需创建一个新的 table。因此,当您尝试在第 4 行使用 mu 时,它不存在(这将导致错误)。在第 3 行,您将 y 的值设置为与 x 相同,但这也意味着相同的 type(整数)。然后稍后当您尝试将 y 重置为 mu 的浮点值时,您会收到 'type 错误。

这是一段与您的代码类似的有效代码:

q)tab2:([]items:`a`b`a`a`b; x:-6 8 0 -3 5)
q)tab2: update mu:avg x by items from tab2
q)tab2: update y:"f"$x from tab2
q)tab2: update y:mu from tab2 where (x>0) and (x> mu)
q)tab2: update y:mu from tab2 where (x<0) and (x<= mu)
q)tab2
items x  mu  y  
----------------
a     -6 -3  -3 
b     8  6.5 6.5
a     0  -3  0  
a     -3 -3  -3 
b     5  6.5 5

您可以在一行中完成此操作:

tab3: update y:?[abs[x]>abs[mu];mu;x] from (update mu:avg x by items from tab2) where x<>0