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

#kdb

#kdb

Вопрос:

У меня есть таблица с 2 столбцами с ключами. Это выглядит так

 date        sym   type  val
2020.01.02  ABC         100
2020.01.02  ABC   a2    200
2020.01.02  ANX         300
2020.01.02  XYZ   a3    400
2020.01.02  XYZ   a2    100
 

Обратите внимание, что type столбец имеет некоторые нулевые значения. Я хочу транспонировать эту таблицу в

 date        sym     type_null   type_a2     type_a3
2020.01.02  ABC     100         200         0
2020.01.02  ANX     300         0           0
2020.01.02  XYZ     0           100         400
 

Обратите внимание, что если type значение равно null, мы присваиваем ему значение 0. Я могу сделать это
update type_a2:?[type_a2=0n;0;type_a2] после того, как таблица была транспонирована. Есть ли более элегантный способ сделать это?

Что касается транспонирования, я понятия не имею, как это сделать. Я попробовал следующее, но это не сработало.

 P:asc exec distinct type from myTable;
pvt:exec P#(type!val) by date,sym from myTable;
 

Ответ №1:

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

С точки зрения фактического кода, это, кажется, работает нормально для меня с измененным именем столбца.

 q)myTable:([]date:2020.01.02;sym:`ABC`ABC`ANX`XYZ`XYZ;typ:``a2``a3`a2;val:100 200 300 400 100)
q)P:`$"type_",/:asc exec string distinct typ from myTable
q)0!0^exec P#((`$"type_",/:string[typ])!val) by date,sym from myTable
date       sym type_ type_a2 type_a3
------------------------------------
2020.01.02 ABC 100   200     0
2020.01.02 ANX 300   0       0
2020.01.02 XYZ 0     100     400
 

Я использовал 0^ здесь, чтобы заполнить все нулевые записи таблицы 0 и 0! отменить ввод таблицы.

Комментарии:

1. Спасибо, я попробовал ваш код, и он работает с вашей таблицей, но когда я переключился на свою таблицу, я получил ошибку «длина». Я попробовал exec P#(trdType!val) by date,sym from date sym xasc myTable; и получил таблицу в нужном формате, но все пусто, кроме столбцов date и sym. Я попытался добавить 0!0 ^ и все равно 0

Ответ №2:

Обратите внимание, что не рекомендуется называть столбцы ключевыми словами (вы теряете возможность использовать QSql), но вы все равно можете обойти это с помощью функциональной формы:

 q)table:flip `date`sym`type`val!(2020.01.02;`ABC`ABC`ANX`XYZ`XYZ;``a2``a3`a2;100 200 300 400 100)
q)parse"update `null^type from table"
!
`table
()
0b
(,`x)!,(^;,`null;@:)
q)table:![table;();0b;enlist[`type]!enlist(^;enlist`null;`type)]
q)P:`$?[table;();();(string;(distinct;`type))]
q)0!0^?[table;();{x!x}`date`sym;(#;`P;(!;`type;`val))]
date       sym null a2  a3
---------------------------
2020.01.02 ABC 100  200 0
2020.01.02 ANX 300  0   0
2020.01.02 XYZ 0    100 400
q)`date`sym`type_null`type_a2`type_a3 xcol 0!0^?[table;();{x!x}`date`sym;(#;`P;(!;`type;`val))]
date       sym type_null type_a2 type_a3
----------------------------------------
2020.01.02 ABC 100       200     0
2020.01.02 ANX 300       0       0
2020.01.02 XYZ 0         100     400
 

Применение синтаксического анализа к оператору QSql, записанному в виде строки, вернет внутреннее представление функциональной формы.

Ответ №3:

Более общая функция pivot (здесь ) работает из коробки и даже работает с вашим столбцом с именем type …. хотя, как говорили другие, вам определенно следует избегать столбца с именем type .

 q)myTable:flip`date`sym`type`val!(5#2020.01.02;`ABC`ABC`ANX`XYZ`XYZ;``a2``a3`a2;100 200 300 400 100)
q)0^piv[myTable;`date`sym;1#`type;`val;{`$raze each"type_",/:string`null^y};{x,z}]
date       sym| type_null type_a2 type_a3
--------------| -------------------------
2020.01.02 ABC| 100       200     0
2020.01.02 ANX| 300       0       0
2020.01.02 XYZ| 0         100     400