theQDude
theQDude

Reputation: 31

KDB+ Extracting nth element from enlist rows in a table

Sorry for the trivial question. However I think I can figured out a couple of solutions but still not sure. I have the following table

t:flip `sym`exchange`bid`bsze!flip (
    (`IBM;`A;100.9 100.8 100.7 100.8; 100 200 300 400);
    (`FB;`A;100.4 100.3 100.2;100 200 300))

I want to extract the second element from the rows an assign it to a variable, I can do this using the following

[t`bid][;1]

However when I try to assign the value I get an error. For example

x:[t`bid][;1]

I get the following error

ERROR: 'y 
(attempt to use variable y without defining/assigning first (or user-defined signal))

Also I can use

x:first each t`bid

But in this case how do I get the second level

Thank you for the help.

Upvotes: 1

Views: 1463

Answers (3)

SJT
SJT

Reputation: 1097

Tables are indexed first by row, second by column. Eliding an index gets you all values for it.

q)t[1;`bid]
100.4 100.3 100.2

q)t[;`bid]  / all rows
100.9 100.8 100.7 100.8
100.4 100.3 100.2

Table columns are always indexed as symbols; rows as integers. Confusion arises, because q exploits that difference to support a shorthand:

q)t[`bid]  / i.e. t[;`bid]
100.9 100.8 100.7 100.8
100.4 100.3 100.2
q)t`bid   / i.e. t[;`bid]
100.9 100.8 100.7 100.8
100.4 100.3 100.2

From this you can see the concise way to index the items you want is

q)a:t[;`bid;1]  / all rows; bid column; 2nd item
q)a
100.8 100.3

Going beyond the OP, you might prefer a different scheme for t. Clearly bid and bsze are to conform for each row. But nothing in the scheme ensures this. Tabulating them might protect them from corruption.

q)tb8:{flip x!y x}[`bid`bsze]  / tabulate
q)show u:select sym,exchange,bids:tb8 each t from t
sym exchange bids
-----------------------------------------------------------------
IBM A        +`bid`bsze!(100.9 100.8 100.7 100.8;100 200 300 400)
FB  A        +`bid`bsze!(100.4 100.3 100.2;100 200 300)

q)u[0;`bids]
bid   bsze
----------
100.9 100
100.8 200
100.7 300
100.8 400

I have extended the Reference article on syntax to describe this:

https://code.kx.com/q/basics/syntax/#indexing-tables

Upvotes: 0

Maurice Lim
Maurice Lim

Reputation: 883

[t`bid][;1] is technically not the correct syntax.

q)1+[t`bid][;1]
'type
  [0]  1+[t`bid][;1]
       ^
q)1+t[`bid][;1]
101.8 101.3

When using square brackets, an expression is usually required on the left side. E.g. a function or variable. Square brackets will evaluate from the "immediate left" first - look at the example @Matthew provided, wheras circle brackets will force the evaluation within first. Right to left evaluation still applies but depending on the brackets used, it overwrites that behaviour.

https://code.kx.com/q/basics/syntax/#bracket-notation has some useful information on bracket notation.

In your case you mentioned you can use first each t`bid - it is equivalent to {x 0}each t`bid. To get the second element using the same method you can use {x 1}each t`bid.

Some additional methods you can consider:

exec bid[;1] from t

Upvotes: 1

Matthew Madill
Matthew Madill

Reputation: 880

if i understand correctly, this should work

q)x:t[`bid][;1]
q)x
100.8 100.3

or equivalently

q)x:(t`bid)[;1]
q)x
100.8 100.3

Upvotes: 2

Related Questions