Q/KDB+:排除空值的百分位数函数



Q 中表示百分位函数(不要与百分位数混淆(的最不冗长的方法是什么,不包括空值?

我有:

q)x:0N 1 2 0N 2 1 5
q)@[count[x]#0Nf;i;:;(1%count i)*1+rank x i:where not null x]
0n 0.2 0.6 0n 0.8 0.4 1

上述rank的问题在于,领带实际上并没有以相等的概率/百分位值结束。

虽然我不认为这是最佳解决方案,但它应该可以解决问题:

{   
  X: x where not null x; 
  grouped: group asc X;
  firstRank: first each value grouped;
  quantiles: (key grouped)! firstRank%count X;
  quantiles x
}[0N 1 2 0N 2 1 5]

代码

  1. 从输入数组中筛选出空值
  2. 按升序对数组进行排序,并按每个元素对其进行分组。这给出了下一个结构的地图 1 2 5 !(0 1; 2 3; 4(
  3. 按键获取第一个索引:1 2 5 ! 0 2 4
  4. 获取基于 (3( 的分位数函数值
  5. 将输入数组元素映射到相应的分位数

我比较了几种方法(包括来自另一个答案的prank4(:

prank1:{
  n:asc x where not null x;
  (sums[count each group n]%count n) @ x
  }
prank2:{
  p:(1+(asc n) bin n)%count n:x i:where not null x;
  @[count[x]#0Nf;i;:;p]
  }
prank3:{@[((1+til[count i])%count i)@last each group asc i:x where not null x;x]}
prank4:{   
  X: x where not null x; 
  grouped: group asc X;
  firstRank: first each value grouped;
  quantiles: (key grouped)! firstRank%count X;
  quantiles x
  }

检查输出是否与最接近的百分位数计算排名方法一致,但prank4除外:

prank1 0N 1 2 0N 2 1 5 / 0n 0.4 0.8 0n 0.8 0.4 1

比较计时和内存占用:

x:10000000?0N,til 500
ts prank1 x  /  494 402661632
ts prank2 x  / 3905 671088960
ts prank3 x  /  552 536879392
ts prank4 x  /  496 533741888
prank2[x]~prank1 x / 1b
prank1[x]~prank3 x / 1b
prank1[x]~prank4 x / 0b

最新更新