(q / kdb +) Обновление строк с использованием результатов предыдущих строк - PullRequest
0 голосов
/ 06 сентября 2018

Использование таблицы

t:([]c1: 3 4 7 2 4.0;c2: 2 8 10 1 9.0;c3:5 8 13 2 11.0)

c1  c2  c3
3   2   5
4   8   8
7   10  13
2   1   2
4   9   11

Мне нужно обновить 3 новых столбца (c1M,c2M,c3M), где:

  • для первого ряда:

    • c1M:avg(c1,c2,c3)
    • c2M:avg(c1,c2)
    • c3M:c3
  • другие строки:

    • c1M:avg(c1,c2,c3)
    • c2M:avg(prev c1M,prev c2M)
    • c3M:max(c3,c1M,c2M)

Я могу сделать первый ряд, используя

t:update c1M:avg(c1,c2,c3),c2M:avg(c1,c2),c3M:c3 from t where i=0

c1  c2  c3  c1M c2M c3M
3   2   5   3.3 2.5 5
4   8   8   0n  0n  0N
7   10  13  0n  0n  0N
2   1   2   0n  0n  0N
4   9   11  0n  0n  0N

Не уверен, как действовать жестко. Я пробовал что-то вроде:

update c1M:avg(c1;c2;c3),c2M:avg(prev c1M;prev c2M),c3M:c3|c1M|c2M from t where i>0

Но не повезло.

Результат для этого примера должен быть:

c1  c2  c3  c1M c2M c3M
3   2   5   3.3 2.5 5.0
4   8   8   6.7 2.9 8.0
7   10  13  10  4.8 13.0
2   1   2   1.7 7.4 7.4
4   9   11  8.0 4.5 11.0

Может кто-нибудь мне помочь?

Ответы [ 4 ]

0 голосов
/ 06 сентября 2018

Альтернативный подход, вероятно, не самый быстрый, но меньший объем кода

q){y,`c1M`c2M`c3M!a,max y[`c3],a:(avg y;avg y[`c1`c2]^x`c1M`c2M)}\[t@-1;t]
c1 c2 c3 c1M      c2M      c3M
-----------------------------------
3  2  5  3.333333 2.5      5
4  8  8  6.666667 2.916667 8
7  10 13 10       4.791667 13
2  1  2  1.666667 7.395833 7.395833
4  9  11 8        4.53125  11
0 голосов
/ 06 сентября 2018

KDB + намного быстрее при векторных вычислениях, чем при итерации. Из-за этого возможно более быстрый способ сделать это - выполнить итерацию только по столбцу c2M, используя наречие, поскольку оно является единственным, для которого требуется предыдущее значение из столбца. Я думаю, что вы можете искать это:

update c3M:c3 from (update c3M:max(c3;c1M;c2M) from update c2M:{avg x,y}\[first 
c2;first[c1],1_prev c1M] from update c1M:avg(c1;c2;c3) from t) where i=0

Это выполняется быстрее, чем итерация и выполнение вычислений по всей таблице, например:

q)\ts:1000 ({update c3M:max(c3;c1M;c2M),c2M:c2M^avg(prev c1M;prev 
c2M),c1M:c1M^avg(c1;c2;c3) from x}/)[update 
c1M:avg(c1,c2,c3),c2M:avg(c1,c2),c3M:c3 from t where i=0]
53 7568

q)\ts:1000 update c3M:c3 from (update c3M:max(c3;c1M;c2M) from update c2M: 
{avg x,y}\[first c2;first[c1],1_prev c1M] from update c1M:avg(c1;c2;c3) from 
t) where i=0
11 6896
0 голосов
/ 06 сентября 2018
q) nt:update c1m:avg(c1;c2;c3) from t 
q) nt:update c2m:-1_({avg x,y}\[avg[c1[0],c2[0]],c1m]) from nt
q) nt:update c3m:(c3[0],1_max(c3;c1m;c2m)) from nt
0 голосов
/ 06 сентября 2018

Я думаю, что то, что вы ищете здесь, закончилось: http://code.kx.com/q/ref/adverbs/#over

Он будет перебирать каждую строку таблицы

q)({update c3M:max(c3;c1M;c2M),c2M:c2M^avg(prev c1M;prev c2M),c1M:c1M^avg(c1;c2;c3) from x}/)[update c1M:avg(c1,c2,c3),c2M:avg(c1,c2),c3M:c3 from t where i=0] 
c1 c2 c3 c1M c2M c3M
--------------------
3  2  5  3.3 2.5 5  
4  8  8  6.7 2.9 8  
7  10 13 10  4.8 13 
2  1  2  1.7 7.4 7.4
4  9  11 8   4.5 11     
...