#kdb
#kdb
Вопрос:
Я пытаюсь выполнить некоторую простую логику в таблице, но я хотел бы убедиться, что столбцы существуют, прежде чем делать это в качестве шага проверки. Мои данные состоят из стандартных имен таблиц, хотя они не всегда присутствуют в каждом источнике данных.
Хотя следующее, похоже, работает (в настоящее время просто проверяет AAA) Мне нужно расширить, чтобы убедиться, что PRI_AAA (и, в конечном итоге, многие другие переменные) также присутствуют.
t: $[`AAA in cols `t; temp: update AAA_VAL: AAA*AAA_PRICE from t;()]
Вопрос из двух частей
-
Это кажется довольно утомительным для каждой переменной (представьте
AAA-ZZZ
входные данные и их производные). Есть ли умный способ использовать словарь (или таблицу), чтобы узнать, существует ли количество переменных, или вставить столбец с нулями, если они этого не делают? -
Аналогично, можем ли мы сохранить формулу или инструкции для применения в словаре (или таблице) для проверки и возврата вычисления (т. Е.
BBB_VAL: BBB*BBB_PRICE
.) Некоторые вычисления будут зависеть от других (например,BBB_Tax_Basis = BBB_VAL - BBB_COSTS
затрат, поэтому могут возникнуть итеративные проблемы.
Заранее благодарю!
Ответ №1:
Функциональное обновление может быть лучшим способом достижения этой цели, если вы намерены обновить многие столбцы таблицы аналогичным образом.
func:{[t;x]
if[not x in cols t;t:![t;();0b;(enlist x)!enlist 0]];
:$[x in cols t;
![t;();0b;(enlist`$string[x],"_VAL")!enlist(*;x;`$string[x],"_PRICE")];
t;
];
};
Эта функция обновит t
*_VAL
столбцы для любого столбца, который вы передаете в качестве аргумента, при этом сначала также добавит нулевой столбец для любых отсутствующих столбцов, переданных в качестве аргумента.
q)t:([]AAA:10?100;BBB:10?100;CCC:10?100;AAA_PRICE:10*10?10;BBB_PRICE:10*10?10;CCC_PRICE:10*10?10;DDD_PRICE:10*10?10)
q)func/[t;`AAA`BBB`CCC`DDD]
AAA BBB CCC AAA_PRICE BBB_PRICE CCC_PRICE DDD_PRICE AAA_VAL BBB_VAL CCC_VAL DDD DDD_VAL
---------------------------------------------------------------------------------------
70 28 89 10 90 0 0 700 2520 0 0 0
39 17 97 50 90 40 10 1950 1530 3880 0 0
76 11 11 0 0 50 10 0 0 550 0 0
26 55 99 20 60 80 90 520 3300 7920 0 0
91 51 3 30 20 0 60 2730 1020 0 0 0
83 81 7 70 60 40 90 5810 4860 280 0 0
76 68 98 40 80 90 70 3040 5440 8820 0 0
88 96 30 70 0 80 80 6160 0 2400 0 0
4 61 2 70 90 0 40 280 5490 0 0 0
56 70 15 0 50 30 30 0 3500 450 0 0
Как вы уже упоминали, чтобы охватить пункт 2, словарь функций может быть лучшим способом.
q)dict:raze{(enlist`$string[x],"_VAL")!enlist(*;x;`$string[x],"_PRICE")}each`AAA`BBB`DDD
q)dict
AAA_VAL| * `AAA `AAA_PRICE
BBB_VAL| * `BBB `BBB_PRICE
DDD_VAL| * `DDD `DDD_PRICE
А затем слегка измененная функция…
func:{[dict;t;x]
if[not x in cols t;t:![t;();0b;(enlist x)!enlist 0]];
:$[x in cols t;
![t;();0b;(enlist`$string[x],"_VAL")!enlist(dict`$string[x],"_VAL")];
t;
];
};
дает аналогичный результат.
q)func[dict]/[t;`AAA`BBB`DDD]
AAA BBB CCC AAA_PRICE BBB_PRICE CCC_PRICE DDD_PRICE AAA_VAL BBB_VAL DDD DDD_VAL
-------------------------------------------------------------------------------
70 28 89 10 90 0 0 700 2520 0 0
39 17 97 50 90 40 10 1950 1530 0 0
76 11 11 0 0 50 10 0 0 0 0
26 55 99 20 60 80 90 520 3300 0 0
91 51 3 30 20 0 60 2730 1020 0 0
83 81 7 70 60 40 90 5810 4860 0 0
76 68 98 40 80 90 70 3040 5440 0 0
88 96 30 70 0 80 80 6160 0 0 0
4 61 2 70 90 0 40 280 5490 0 0
56 70 15 0 50 30 30 0 3500 0 0
Комментарии:
1. Еще раз спасибо Cathal….at в настоящее время я пишу вложенные условные выражения, чтобы проверить и посмотреть, существуют ли обе переменные, и, хотя это работает, это довольно утомительно и возвращает таблицу
t
, если какая-либо из переменных не существует:t: $[
AAA в столбцахt; $[
AAA_PRICE в столбцахt; t: update AAA_Revenue: AAA_Revenue (AAA*AAA_PRICE) from t; t];t];
для каждой переменной. Единственное, что меня беспокоит, это зависимые вычисления, хотя я предполагаю, что каждая функция и словарь могут быть дискретными (т. Е. Налоговый словарь зависит от словаря доходов и т. Д.) Еще раз спасибо, я собираюсь протестировать это сегодня утром!
Ответ №2:
Вот еще один подход, который обрабатывает зависимые / каскадные вычисления, а также определяет, какие вычисления возможны или нет, в зависимости от доступных столбцов в таблице.
q)show map:`AAA_VAL`BBB_VAL`AAA_RevenueP`AAA_RevenueM`BBB_Other!((*;`AAA;`AAA_PRICE);(*;`BBB;`BBB_PRICE);( ;`AAA_Revenue;`AAA_VAL);(%;`AAA_RevenueP;1e6);(reciprocal;`BBB_VAL));
AAA_VAL | (*;`AAA;`AAA_PRICE)
BBB_VAL | (*;`BBB;`BBB_PRICE)
AAA_RevenueP| ( ;`AAA_Revenue;`AAA_VAL)
AAA_RevenueM| (%;`AAA_RevenueP;1000000f)
BBB_Other | (%:;`BBB_VAL)
func:{c:{$[0h=type y;.z.s[x]each y;-11h<>type y;y;y in key x;.z.s[x]each x y;y]}[y]''[y];
![x;();0b;where[{all in[;cols x]r where -11h=type each r:(raze/)y}[x]each c]#c]};
q)t:([] AAA:1 2 3;AAA_PRICE:1 2 3f;AAA_Revenue:10 20 30;BBB:4 5 6);
q)func[t;map]
AAA AAA_PRICE AAA_Revenue BBB AAA_VAL AAA_RevenueP AAA_RevenueM
---------------------------------------------------------------
1 1 10 4 1 11 1.1e-05
2 2 20 5 4 24 2.4e-05
3 3 30 6 9 39 3.9e-05
/if the right columns are there
q)t:([] AAA:1 2 3;AAA_PRICE:1 2 3f;AAA_Revenue:10 20 30;BBB:4 5 6;BBB_PRICE:4 5 6f);
q)func[t;map]
AAA AAA_PRICE AAA_Revenue BBB BBB_PRICE AAA_VAL BBB_VAL AAA_RevenueP AAA_RevenueM BBB_Other
--------------------------------------------------------------------------------------------
1 1 10 4 4 1 16 11 1.1e-05 0.0625
2 2 20 5 5 4 25 24 2.4e-05 0.04
3 3 30 6 6 9 36 39 3.9e-05 0.02777778
Единственное предостережение заключается в том, что ваша карта не может иметь то же имя столбца, что и ключ, и значение вашей карты, иначе говоря, нельзя повторно использовать имена столбцов. И предполагается, что все символы на вашей карте являются именами столбцов (а не глобальными переменными), хотя их можно расширить, чтобы охватить это
РЕДАКТИРОВАТЬ: если у вас есть большое количество сопоставлений столбцов, тогда будет проще определить его более вертикальным способом, например:
map:(!). flip(
(`AAA_VAL; (*;`AAA;`AAA_PRICE));
(`BBB_VAL; (*;`BBB;`BBB_PRICE));
(`AAA_RevenueP;( ;`AAA_Revenue;`AAA_VAL));
(`AAA_RevenueM;(%;`AAA_RevenueP;1e6));
(`BBB_Other; (reciprocal;`BBB_VAL))
);
Комментарии:
1. Спасибо, Терри, мне нужно разобраться с этой функцией. Я все еще не совсем понимаю синтаксис q. Я полагаю, вы понимаете мою цель. Этот
map
словарь может стать довольно большим, но преимуществом будет единый репозиторий для этих базовых расчетов денежных потоков. Для справки, у меня есть ~ 100 строк вложенных условных обновлений для более чем 6,5 мм записей и занимает ~ 1000 мс. Я протестирую сегодня и сообщу, смогу ли я заставить все это работать. ** РЕДАКТИРОВАТЬ ** — Я также не использую никаких глобальных переменных2. ОК. Смотрите мое дополнительное редактирование выше относительно большого количества сопоставлений
3. О, здорово, это значительно упростит сборку!
4. Хороший материал. Рекурсивная
.z.s
логика сканирует карту на наличие вложенных сопоставлений, а затем заменяет их базовыми вычислениями, пока все на карте не будет записано в терминах базовых вычислений для фактических / существующих столбцов таблицы.5. Посмотрите, как parse считывает его и работает с этим :
0N!parse"select totalR:AAA BBB CCC DDD EEE from tab";
. В этом случае вложенных сумм вы можете сгенерировать вложение, используя что-то вроде(1#`TotalRevenue)!enlist{( ;y;x)}/[reverse`AAA`BBB`CCC`DDD`EEE]