There are already moving average in kdb/q.
https://code.kx.com/q/ref/avg/#mavg
But how do I compute moving median?
Here is a naive approach. It starts with an empty list and null median and iterates over the list feeding in a new value each time.
Sublist is used fix the window, and this window is passed along with the median as the state of into the next iteration.
At the end scan \ will output the state at every iteration from which we take the median (first element) from each one
mmed:{{(med l;l:neg[x] sublist last[y],z)}[x]\[(0n;());y][;0]}
q)mmed[5;til 10]
0 0.5 1 1.5 2 3 4 5 6 7
q)i:4 9 2 7 0 1 9 2 1 8
q)mmed[3;i]
4 6.5 4 7 2 1 1 2 2 2
There's also a generic "sliding window" function here which you can pass your desired aggregator into: https://code.kx.com/q/kb/programming-idioms/#how-do-i-apply-a-function-to-a-sequence-sliding-window
q)swin:{[f;w;s] f each { 1_x,y }\[w#0;s]}
q)swin[avg; 3; til 10]
0 0.33333333 1 2 3 4 5 6 7 8
q)update newcol:swin[med;10;mycol] from tab
Related
i have data A=( 3,5,3,1,4 ) in a column and
B=[
4 6 9 1 3
2 7 2 5 7
7 3 1 8 2
4 1 6 9 1
2 5 8 3 6 ]
And i want: as in A first element is 3 and for this i want to get first element of column 3 row 1 from B which is 9. The second element of A is 5 and for this i want to get the the 2nd element of column 5 and row 2 from B which is 7 ,and do the process for all other elements . how to do this in matlab? the required elements are bold and underlined. The desired output is [9,7,1,4,3]
Read about linear indexes.
sub2ind will convert from [row col] to index.
Cols=[ 3,5,3,1,4 ];
Rows=1:length(Cols);
B=[
4 6 9 1 3
2 7 2 5 7
7 3 1 8 2
4 1 6 9 1
2 5 8 3 6 ];
Indexes=sub2ind(size(B),Rows,Cols);
Vals=B(Indexes)
if I've read well you want an elements replacement. It's quite simple
A(1)=B(1,3)
A(2)=B(2,5)
So after you have declared your two vectors you can handle them replacing singular components. In general when you have a 1-D vectors you can access to it's component position only declaring the position itself inside the parentheses, as I did for A.
Whe you have to face situation like in B, If you remember linear algebra and matrix in general B(a,b) means the element of matrix B placed in the line a and column b so you have to specify row and column to access that element.
If you have a random matrix, for example a 5x5:
A(i,j) = (5 4 3 2 1
4 3 2 1 0
5 4 3 2 1
4 3 2 1 0
5 4 3 2 1)
And a second array:
B(1,j) = (4 5 6 7 8)
How can I then assign values of B to A if this only needs to be done when the value of B(1,j) is larger than any of the values from a certain colomn of A?
For example, B(1,1) = 4 and in the first colomn of A it is larger than A(1,1), A(3,1) and A(5,1), so these must be replaced by 4. In the second colomn, nothing needs to be replaced, etc.
Thanks already!
You can do this without any explicit looping using bsxfun:
A = [5 4 3 2 1
4 3 2 1 0
5 4 3 2 1
4 3 2 1 0
5 4 3 2 1];
B = [4 5 6 7 8];
A = bsxfun(#min,A,B);
Result:
A =
4 4 3 2 1
4 3 2 1 0
4 4 3 2 1
4 3 2 1 0
4 4 3 2 1
In later versions of MATLAB (2016b and later) you can even omit the bsxfun and get the same result.
A = min(A,B);
Matlab "find" may be of use to you.
https://www.mathworks.com/help/matlab/matlab_prog/find-array-elements-that-meet-a-condition.html
If you aren't concerned about speed or efficiency, you could also set up a two nested for loops with a condition (i.e. an if) statement comparing the values of A and B.
If you only interested in column wise comparison to B, you could use the increment of the outer loop in the inner loop.
for i,...
for j,...
if B(1,i) > A(j,i)
A(j,i)=B(i,j)
I'm struggling to understand this q code programming idiom from the kx cookbook:
q)swin:{[f;w;s] f each { 1_x,y }\[w#0;s]}
q)swin[avg; 3; til 10]
0 0.33333333 1 2 3 4 5 6 7 8
The notation is confusing. Is there an easy way to break it down as a beginner?
I get that the compact notation for the function is probably equivalent to this
swin:{[f;w;s] f each {[x; y] 1_x, y }\[w#0;s]}
w#0 means repeat 0 w times (w is some filler for the first couple of observations?), and 1_x, y means join x, after dropping the first observation, to y. But I don't understand how this then plays out with f = avg applied with each. Is there a way to understand this easily?
http://code.kx.com/q/ref/adverbs/#converge-iterate
Scan (\) on a binary (two-param) function takes the first argument as the seed value - in this case 3#0 - and iterates through each of the items in the second list - in this case til 10 - applying the function (append new value, drop first).
q){1_x,y}\[3#0;til 10]
0 0 0
0 0 1
0 1 2
1 2 3
2 3 4
3 4 5
4 5 6
5 6 7
6 7 8
7 8 9
So now you have ten lists and you can apply a function to each list - in this case avg but it could be any other function that applies to a list
q)med each {1_x,y}\[3#0;til 10]
0 0 1 2 3 4 5 6 7 8f
q)
q)first each {1_x,y}\[3#0;til 10]
0 0 0 1 2 3 4 5 6 7
q)
q)last each {1_x,y}\[3#0;til 10]
0 1 2 3 4 5 6 7 8 9
I need some help please. I have an array, as shown below, 6 rows and 5 columns, none of the elements in any one row repeats. The elements are all single digit numbers.
I want to find out, per row, when a number, let's say 1 appears, I want to keep of how often the other numbers of the row appear. For example, 1 shows up 3 times in rows one, three and five. When 1 shows up, 2 shows up one time, 3 shows up two times, 4 shows up two times, 5 shows up one time, 6 shows up two times, 7 shows up one time, 8 shows up three times, and 9 shows up zero times. I want to keep a vector of this information that will look like, V = [3,1,2,2,1,2,1,3,0], by starting with a vector like N = [1,2,3,4,5,6,7,8,9]
ARRAY =
1 5 8 2 6
2 3 4 6 7
3 1 8 7 4
6 5 7 9 4
1 4 3 8 6
5 7 8 9 6
The code I have below does not give the feedback I am looking for, can someone help please? Thanks
for i=1:length(ARRAY)
for j=1:length(N)
ARRAY(i,:)==j
V(j) = sum(j)
end
end
Using indices that is in A creae a zero and one 6 * 9 matrix that [i,j] th element of it is 1 if i th row of A contains j.
Then multiply the zero and one matrix with its transpose to get desirable result:
A =[...
1 5 8 2 6
2 3 4 6 7
3 1 8 7 4
6 5 7 9 4
1 4 3 8 6
5 7 8 9 6]
% create a matrix with the size of A that each row contains the row number
rowidx = repmat((1 : size(A,1)).' , 1 , size(A , 2))
% z_o a zero and one 6 * 9 matrix that [i,j] th element of it is 1 if i th row of A contains j
z_o = full(sparse(rowidx , A, 1))
% matrix multiplication with its transpose to create desirable result. each column relates to number N
out = z_o.' * z_o
Result: each column relates to N
3 1 2 2 1 2 1 3 0
1 2 1 1 1 2 1 1 0
2 1 3 3 0 2 2 2 0
2 1 3 4 1 3 3 2 1
1 1 0 1 3 3 2 2 2
2 2 2 3 3 5 3 3 2
1 1 2 3 2 3 4 2 2
3 1 2 2 2 3 2 4 1
0 0 0 1 2 2 2 1 2
I don't understand how you are approaching the problem with your sample code but here is something that should work. This uses find, any and accumarray and in each iteration for the loop it will return a V corresponding to the ith element in N
for i=1:length(N)
rowIdx = find(any(A == N(i),2)); % Find all the rows contain N(j)
A_red = A(rowIdx,:); % Get only those rows
V = [accumarray(A_red(:),1)]'; % Count occurrences of the 9 numbers
V(end+1:9) = 0; % If some numbers don't exist place zeros on their counts
end
I've got a matrix (n x m). And I'd like to know, for each row, the indexes of the coloums that contain the first two maximum values:
2 3 4 2
2 4 7 1
1 1 2 4
5 5 9 6
1 4 2 1
9 8 1 2
The answer should be:
2 3
2 3
3 4
3 4
2 3
1 2
How can I obtain it with matlab commands? I'd like not to use for loops. I tried with:
[x,y]=max(matrix')
y=y';
y gives me the colum indexes for the maximum elements. Now I'd set to zero these elements and repeat the instructions but I have no idea how to do. I treid:
matrix(:,y)=0;
but it doesn't work.
if A is your matrix, then sort and pick the top two indices,
[a ix]=sort(A,2)
ans= ix(:,end-1:end)