Альтернатива использованию ungroup в kdb? - PullRequest
0 голосов
/ 07 апреля 2020

У меня есть две таблицы в KDB.

Один из них представляет собой серию времени со столбцом даты-времени, символьным столбцом (охватывающим несколько дат, например, могут быть строки 1 мм или 2 мм). Каждый момент времени имеет одинаковое количество символов и несколько других стандартных столбцов, таких как цена. Давайте назовем это t1:

`date`datetime`sym`price

Другая таблица имеет следующую структуру:

`date`sym`factors`weights 

где factor - список, а weights - список равной длины для каждого sym. Давайте назовем это t2.

Я делаю левое соединение этих двух таблиц, а затем разгруппируюсь. факторы и веса имеют неодинаковую длину для каждого сим.

Я делаю следующее:

select sum (weights*price) by date, factors from ungroup t1 lj `date`sym xkey t2 

Однако это очень медленно и может длиться 5-6 секунд, если t1 имеет миллион строк или больше.

Позвоните всем экспертам KDB за советом!

РЕДАКТИРОВАТЬ:

вот полный пример: (извиняюсь за окольный способ определения t1 и t2)

interval: `long$`time$00:01:00; 
hops: til 1+ `int$((`long$(et:`time$17:00)-st:`time$07:00))%interval;
times: st + `long$interval*hops; 
dates: .z.D - til .z.D-.z.D-10; 
timepoints: ([] date: dates) cross ([] time:times); 
syms: ([] sym: 300?`5); 
universe: timepoints cross syms; 
t1: update datetime: date+time, price:count[universe]?100.0 from universe;
t2: ([] date:dates) cross syms; 
/ note here my real life t2, doesn't have a count of 10 weights/factors for each sym, it can vary by sym. 
t2: `date`sym xkey update factors: count[t2]#enlist 10?`5, weights: count[t2]#enlist 10?10 from t2; 

/ what is slow is the ungroup 
select sum weights*price by date, datetime, factors from ungroup t1 lj t2


1 Ответ

1 голос
/ 08 апреля 2020

Один из способов избежать разгруппировки - это работать с матрицами (или списками списков) и использовать преимущества оптимизированного умножения матриц $, видимого здесь: https://code.kx.com/q/ref/mmu/

В моем подходе ниже, вместо того, чтобы соединить t2 с t1, чтобы разгруппировать, я группирую t1 и соединяюсь с t2 (таким образом сохраняя все как списки списков), а затем использую некоторую матричную манипуляцию (с окончательной разгруппировкой в ​​конце на гораздо меньшем множестве)

q)\ts res:select sum weights*price by date, factors from ungroup t1 lj t2
4100 3035628112
q)\ts resT:ungroup exec first factors,sum each flip["f"$weights]$price by date:date from t2 lj select price by date,sym from t1;
76 83892800

q)(0!res)~`date`factors xasc `date`factors`weights xcol resT
1b

Как вы можете видеть, это намного быстрее (по крайней мере, на моем компьютере), и результат идентичен, за исключением порядка и имен столбцов.

Возможно, вам все же придется немного изменить это решение, чтобы оно работало в вашем фактическом сценарии использования (с переменными весами и т. Д. c) - в этом случае, возможно, при необходимости принудительно задайте одинаковое количество весов для каждого символа, заполняя нулями при необходимости )

...