изменить строки таблицы в соответствии с нулевыми значениями

Я новичок в kdb+q. Я столкнулся со следующей проблемой, связанной с таблицами, в одном из моих упражнений.

Имея ключевую таблицу t с единственным ключом = id, напишите функцию, которая возвращает другую таблицу T, такую ​​что:

а) Для каждой строки в t имеется столько строк в T, сколько ненулевых значений в этой строке t.

б) Каждая строка в T содержит ровно одно ненулевое значение, которое должно совпадать с соответствующим ненулевым значением в t.

Примеры:

If t is

id |a    b
----------
1  |1    1
2  |1    0n

then T would be

id | a    b
-----------
1  |1    0n
1  |0n   1
2  |1    0n

and if t is
id  | a    b    c
------------------ 
1   | 1    3    0n
2   | 2    0n   4
3   | 0n   0n   5

then T would be

id |a     b    c
----------------
1  |1     0n   0n
1  |0n    3    0n
2  |2     0n   0n
2  |0n    0n   4
3  |0n    0n   5

Из того, что я вывел из вопроса, если мы рассматриваем каждую строку как n-кортеж, он проецирует вектор вдоль каждого из его n измерений, где 0n ведет себя как 0 в обычном декартовом векторе.

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

Кто-нибудь может мне с этим помочь ?


kdb
person pikachuchameleon    schedule 10.06.2014    source источник
comment
Предлагаю убрать sql из списка тегов - это не имеет отношения к sql :)   -  person Manish Patel    schedule 12.06.2014


Ответы (3)


Вот что у меня вышло:

q)f
{ungroup x{(x*y)@\:where not null get x}\:{(x;x)#1,x#0N}count[cols x]-1}
q)t:([id:1 2 3]a:1 2 0N;b:3 0N 0N;c:0N 4 5)
q)t
id| a b c
--| -----
1 | 1 3
2 | 2   4
3 |     5
q)f t
id a b c
--------
1  1
1    3
2  2
2      4
3      5
person WooiKent Lee    schedule 10.06.2014
comment
Очень понравилось читать этот ответ! блестяще! Мое единственное замечание заключается в том, что вы рискуете потерять информацию о типе при повышении типа, происходящем при умножении. В конце я попытался выполнить приведение типов, но это слишком сильно замедлило работу. Ничего страшного, но просто мысль стоило выделить - person JPC; 10.06.2014
comment
Приятно слышать, я согласен, что повышение типа будет иметь место, если нули будут другого типа. Наверняка есть способ обойти это :) - person WooiKent Lee; 11.06.2014
comment
Я попытался сделать так, чтобы нули, которые вы берете в начале, соответствовали типам столбцов, но вы все равно теряете определенную информацию при умножении (например, short*short -> int q)(type each n)~type each (1;2h ;3)*n:(1;0Nh;0n) Какой-нибудь трюк, кроме приведения типов? Я, конечно, хотел бы узнать, если это так, спасибо! - person JPC; 11.06.2014
comment
Пытался спросить здесь, но не думаю, что есть чистый способ обойти продвижение типа. Должна быть веская причина для продвижения короткого короткого в целое (может быть, избежать переполнения?). Но на данный момент приведение типов - это путь :) - person WooiKent Lee; 13.06.2014
comment
Да, кажется, что short*short-›int определенно предотвращает переполнение. Спасибо, что поспрашивали! Рад видеть, что тег kdb в последнее время стал очень активным. очень полезно для меня, чтобы начать собирать уловки торговли. - person JPC; 13.06.2014

Вот моя попытка, но значительно медленнее, чем ответ @WooiKent Lee. Я облажался с сортировкой и удалением полностью нулевых строк (но в основном с первыми).

q)breakout:{k xasc n where any each not null v#n:(0#x0) upsert/((k:keys x),/:v:cols value x)#\:x0:0!x}
q)breakout t
id a b c
--------
1  1
1    3
2  2
2      4
3      5
person JPC    schedule 10.06.2014

Этот позаботится о типах (я потрачу немного времени и оптимизирую его)

q)t:([ id: 1 2] a: 1 1;b:1 0n;c: 0N 0Ni)  //checkout the meta
id| a b c
--| -----
1 | 1 1
2 | 1

q)f:{[t] ungroup {st:count[x]#0#enlist x;d:(enlist each key[x])!'(enlist each value[x]); key[x]!flip r where not all each null each r:value each upsert'[st;d]} each   t }

q)f[t]
id a b c
--------
1  1
1    1
2  1

q)meta f[t]
c | t f a
--| -----
id| j
a | j
b | f
c | i
person nyi    schedule 02.07.2018