Jean-Paul
Jean-Paul

Reputation: 21150

kdb+: function with two arguments from columns

I have a function that does something with a date and a function that takes two arguments to perform a calculation. For now let's assume that they look as follows:

d:{[x] :x.hh}
f:{[x;y] :x+y}

Now I want to use function f in a query as follows:

select f each (columnOne,d[columnTwo]) from myTable

Hence, I first want to convert one column to the corresponding numbers using function d. Then, using both columnOne and the output of d[columnTwo], I want to calculate the outcome of f.

Clearly, the approach above does not work, as it fails with a 'rank error.

I've also tried select f ./: (columnOne,'d[columnTwo]) from myTable, which also doesn't work.

How do I do this? Note that I need to input columnOne and columnTwo into f such that the corresponding rows still match. E.g. input row 1 of columnOne and row 1 of columnTwo simultaneously into f.

Upvotes: 1

Views: 2689

Answers (1)

MdSalih
MdSalih

Reputation: 1996

I've also tried select f ./: (columnOne,'d[columnTwo]) from myTable, which also doesn't work.

You're very close with that code. The issue is the d function, in particular the x.hh within function d - the .hh notation doesn't work in this context, and you will need to do `hh$x instead, so d becomes:

d:{[x] :`hh$x}

So making only this change to the above code, we get:

q)d:{[x] :`hh$x}
q)f:{[x;y] :x+y}
q)myTable:([] columnOne:10?5; columnTwo:10?.z.t);
q)update res:f ./: (columnOne,'d[columnTwo]) from myTable
    columnOne columnTwo    res
    --------------------------
    1         21:10:45.900 22
    0         20:23:25.800 20
    2         19:03:52.074 21
    4         00:29:38.945 4
    1         04:30:47.898 5
    2         04:07:38.923 6
    0         06:22:45.093 6
    1         19:06:46.591 20
    1         10:07:47.382 11
    2         00:45:40.134 2

(I've changed select to update so you can see other columns in result table)

Other syntax to achieve the same:

q)update res:f'[columnOne;d columnTwo] from myTable
    columnOne columnTwo    res
    --------------------------
    1         21:10:45.900 22
    0         20:23:25.800 20
    2         19:03:52.074 21
    4         00:29:38.945 4
    1         04:30:47.898 5
    2         04:07:38.923 6
    0         06:22:45.093 6
    1         19:06:46.591 20
    1         10:07:47.382 11
    2         00:45:40.134 2

Only other note worthy point - in the above example, function d is vectorised (works with vector arg), if this wasn't the case, you'd need to change d[columnTwo] to d each columnTwo (or d'[columnTwo])

This would then result in one of the following queries:

select res:f'[columnOne;d'[columnTwo]] from myTable
select res:f ./: (columnOne,'d each columnTwo) from myTable
select res:f ./: (columnOne,'d'[columnTwo]) from myTable

Upvotes: 3

Related Questions