Get range of elements in KDB using variables - kdb

Why I can't use variable inside array ranges in KDB?
test:1 2 3 4 5
This example won't work:
pos:3;
test[1 pos]
but this way it will work
test[1 3]

As you can see, when you use test[1 3], (1 3) is a list. So vector variable requires a list.
q) list1:1 3
q) test[list1]
So you have to use:
q)n:3
q)list1:(1;n)
q)test[list1]
q)test[(1;n)] / alternate way
For detail explanation about why only semicolon doesn't work and why we require brackets '()',check my answer for this post:
kdb/q: how to reshape a list into nRows, where nRows is a variable

To understand what you're asking, consider:
1 2 3 7
That is a simple list of integers. Now consider:
a 2 3
Where a is a vector. The above indexes into a. Easy. Now say you want to have that 2 3 list as a variable
b:2 3
a b //works!
You are specifically asking about how to get a range from a list, this is covered in How to get range of elements in a list in KDB?
In that answer, use variables to create your index list and use the result to index into a

Related

How do I replace the first 10 entries in a column with NaN in KDB

I am doing calculation on columns using summation. I want to manually change my first n entries in my calc column from float to NaN. Can someone please advise me how to do that?
For example, if my column in table t now is mycol:(1 2 3 4 5 6 7 8 9), I am trying to get a function that can replace the first n=4 entries with NaN, so my column in table t becomes mycol:(0N 0N 0N 0N 5 6 7 8 9)
Thank you so much!
Emily
We can use amend functionality to replace the first n items with null value. Additionally, it would be better to use the appropriate null literal for each column based on the type. Something like this would work:
f: {nullDict: "ijfs"!(0Ni;0Nj;0Nf:`); #[x; til y; :; nullDict .Q.ty x]}
This will amend the first y items in the list x. .Q.ty will get the type for input so that we can get the corresponding value from the dictionary.
You can then use this for a single column, like so:
update mycol: f[mycol;4] from tbl
You can also do this in one go for multiple columns with varying number of items to be replaced using functional form:
![tbl;();0b;`mycol`mycol2!((f[;4];`mycol);(f[;3];`mycol2))]
Do take note that you will need to modify nullDict with whatever other types you need.
Update: Thanks to Jonathon McMurray for suggesting a better way to build up nullDict for all primitive types using the below code:
{x!first each x$\:()}.Q.t except " "

Sort rows of a matrix in ascending order

I would like to sort a matrix in ascending order, however I do not want to affect the third column. For example, the sorted version of
A= [ 2 1 3;
5 4 1;
4 3 2]
Would be
B= [1 2 3;
4 5 1;
3 4 2]
Matlab provides quite a bit of inhouse help so using help FUNCTION/CLASS would have provided you with the below information. If you don't know the FUNCTION\CLASS name use lookfor TERM for a list of matches or alternately docsearch TERM.
Stock matlab provides both sort and sortrows. You'll be needing the latter.
sortrows(X,C)
Where C is a list of column indices to sort by whose sign may be positive corresponding for ascending order or negative for descending order.
In your example you'll want this :
sortrows(A',[1,2])'
The ' indicates to matlab that you need the matrix transposed, which basically swaps rows and columns before and after sortrows is called.
You can just sort the 1st two columns and update the matrix accordingly:
edit: updated dimension
A(:,1:2) = sort(A(:,1:2),2);

alternative to reshape or colon in matlab

I want to reduce a two dimensional matrix to row vector.
But using reshape with large matrices is really slow. The other alternative is to use colon, but i want matrix's transpose to be colon and not the matrix itself.
e.g.
A=magic(3)
A =
8 1 6
3 5 7
4 9 2
A(:) will stack up all the columns one by one. but i am looking for something like this:
AA=A(2:3,:)';
and then reshape or colon AA instead of A.
The issue is i dont want to define additional variable like AA.
Is there anyway to reduce dimension of two dimensional matrix without reshape?
You can avoid the additional variable by linear indexing. For your example:
A([2 5 8 3 6 9])
which gives
3 5 7 4 9 2
What's happening here is that you treat A as if it was already transformed into a vector, and the elements of this one-dimensional array are accessed through indices 1 through 9. Using the colon is a special case of linear indexing, A(:) is the same as A(1 : end).
Figuring out the right linear indices can be tricky, but sub2ind can help with that.
It is possible that this slightly speeds up the code, mainly because (as #Shai wrote) you avoid writing data to an intermediate variable. I wouldn't expect too much, though.
Try looking at subsref. For your example, you could use it as follows:
subsref(A',struct('type','()','subs',{{2:3,':'}}))
Update: I misunderstood the original question; I thought the OP wanted to select rows from 2:3 from the transposed A matrix keeping the columns as is. I will keep the previous answer in case it could be useful to others.
I think he/she could use the following to slice and flatten a matrix:
subsref(A(2:3,:)', struct('type','()','subs',{{':'}}))
This would give as output:
[3 5 7 4 9 2]'

how to sum matrix entities as indexing by another vector values?

Suppose I have a vector B=[1 1 2 2] and A=[5 6 7 4] in the form of B says the numbers in the A that are need to be summed up. That is we need to sum 5 and 6 as the first entry of the result array and sum 7 and 4 as the second entry. If B is [1 2 1 2] then first element of the result is 5+7 and second element is 6+4.
How could I do it in Matlab in generic sense?
A fexible and general approach would be to use accumarray().
accumarray(B',A')
The function accumulates the values in A into the positions specified by B.
Since the documentation is not simple to understand I will summarize why it is flexible. You can:
choose your accumulating function (sum by default)
specify the positions as a set of coordinates for accumulation into ND arrays
preset the dimension of the accumulated array (by default it expands to max position)
pad with custom values the non accumulated positions (pads with 0 by default)
set the accumulated array to sparse, thus potential avoiding out of memory
[sum(A(1:2:end));sum(A(2:2:end))]

MATLAB: copy a specific portion of an array

I am trying to copy a few elements from a matrix, but not a whole row, and not a single element.
For example, in the following matrix:
a = 1 2
3 4
5 6
7 8
9 0
How would I copy out just the following data?
b = 1
3
5
i.e. rows 1:3 in column 1 only... I know that you can remove an entire column like this:
b = a(:,1)
... and I appreciate that could just do this and then dump the last two rows, but I'd like to use more streamlined code as I am running a very resource-intensive solution.
Elements in a matrix in MATLAB are stored in column-major order. Which means, you could even use a single index and say:
b = a(1:3);
Since the first 3 elements ARE 1,3,5. Similarly, a(6) is 2, a(7) is 4 etc. Look at the sub2ind method to understand more:
http://www.mathworks.com/help/techdoc/ref/sub2ind.html
You are not "removing" the second column, you are referencing the other column.
You should read some of the Matlab docs, they provide some help about the syntax for accessing portions of matrices:
http://www.mathworks.com/help/techdoc/learn_matlab/f2-12841.html#f2-428