Reputation: 2785
What is the most robust way to specify rules for formatting table values? I want to apply each rule to its corresponding column in the most efficient way. I suppose using the functional form would be helpful in this case.
Here is the sample table:
tbl:flip `GARP`longWgt`shortWgt`longWgtBeta`shortWgtBeta`longWgtRisk`shortWgtRisk`netWgt`netExposure`relativeBeta`relativeRisk`adjBeta`adjRisk!(`GARP_AUTOS_CA`GARP_BANKS_CA`GARP_CHEMICALS_CA`GARP_COMMUNICATIONS_CA`GARP_CONS_DISCR_CA;0.0091686 0.0176234 0.0076484 0.0131509 0.0460397;-0.010305 -0.0470135 0n -0.0078549 -0.0563819;1.3522162 0.6234817 1.3140238 0.7327634 1.1802914;0.1440806 0.7642193 0n 0.7216727 0.6112765;0.3254744 0.1573925 0.2541326 0.2554008 0.350877;0.3079491 0.2218098 0n 0.2594863 0.2758658;-0.0011365 -0.0293902 0.0076484 0.005296 -0.0103422;0.8897173 0.374857 0n 1.67422 0.8165681;9.3851363 0.8158414 0n 1.0153681 1.9308631;1.0569097 0.7095833 0n 0.9842553 1.2719117;8.3501184 -3.269856 0n 1.6999496 1.5766812;-1.0634328 -3.7595078 0n 1.64786 1.0386025)
I want all the columns to have 2 significant figures. The longWgt, shortWgt and netWgt
columns should be in percent.
I have something like this, but I'm sure there is a better way of doing this:
tbl:update longWgt:100f*longWgt, shortWgt:100f*shortWgt, netWgt:100f*netWgt from tbl;
tbl:update .Q.f[2] each longWgt, .Q.f[2] each shortWgt, .Q.f[2] each longWgtBeta, .Q.f[2] each shortWgtBeta, .Q.f[2] each longWgtRisk, .Q.f[2] each shortWgtRisk, .Q.f[2] each netWgt, .Q.f[2] each netExposure, .Q.f[2] each relativeBeta, .Q.f[2] each relativeRisk, .Q.f[2] each adjBeta, .Q.f[2] each adjRisk from tbl;
tbl:update {x,"%"} each longWgt, {x,"%"} each shortWgt, {x,"%"} each netWgt from tbl;
Upvotes: 1
Views: 1833
Reputation: 1780
You could also use the 3 argument form of the @
apply operator which can be found here https://code.kx.com/wiki/Reference/AtSymbol since you are only applying functions to columns and not aggregating, filtering or renaming any columns.
It indexes into the item specified in the first argument with the 2nd argument and then applies the function in 3rd argument to the resulting elements, leaving the other elements untouched.
@[`tbl;wgtCols;100*];
@[`tbl;allCols;.Q.f[2]'];
@[`tbl;wgtCols;{x,'"%"}];
These can be nicely merged into one function using each both '
which will iterate through the list of arguments, applying them in turn. Information on each-both can be found https://code.kx.com/q/ref/adverbs/#each-both
@[`tbl;;]'[(wgtCols;allCols;wgtCols);(100*;.Q.f[2]';{x,'"%"})]]
These will all amend in place, e.g overwrite the tbl
variable. If you do not want this to happen you can use this function:
@[;;]/[tbl;(wgtCols;allCols;wgtCols);(100*;.Q.f[2]';{x,'"%"})]
This utilises the /
(scan) operator to apply each function in turn, with the first function operating on the initial table and the results feeding into the next function.
Upvotes: 2
Reputation: 1663
How about using a functional query:
First multiply the wgtCols
below by 100
:
wgtCols: `longWgt`shortWgt`netWgt;
![`tbl;();0b;wgtCols!{(*;100f;x)} each wgtCols];
Then format all columns allCols
except the `GARP
with 2 decimals:
allCols:1_cols tbl;
![`tbl;();0b;allCols!{(each;.Q.f[2];x)} each allCols];
Finally format the wgtCols
to percentage format:
![`tbl;();0b;wgtCols!{(each;{x,"%"};x)} each wgtCols]
NB: To find out how to construct your functional query, you can use the parse
operator on the q-query of your choice:
parse "update longWgt:100f*longWgt, shortWgt:100f*shortWgt, netWgt:100f*netWgt from tbl"
Output:
!
`tbl
()
0b
`longWgt`shortWgt`netWgt!((*;100f;`longWgt);(*;100f;`shortWgt);(*;100f;`netWgt))
Upvotes: 5