Manipulate specific regions of matrix - matlab

I want to make a manipulate a matrix/look-up table in matlab. Here is the Matrix I am working with:
0 5 10 15 20 25 30 35 40 45 50
0 3 4 5 6 4 5 5 5 5 5
20 3 4 5 6 4 5 5 5 5 5
27 3 4 5 6 4 5 5 5 5 5
34 3 4 5 6 4 5 5 5 5 5
41 3 4 5 6 4 5 5 5 5 5
49 3 4 5 6 4 5 5 5 5 5
56 3 4 5 6 4 5 5 5 5 5
63 3 4 5 6 4 5 5 5 5 5
71 3 4 5 6 4 5 5 5 5 5
78 3 4 5 6 4 5 5 5 5 5
85 3 4 5 6 4 5 5 5 5 5
93 3 4 5 6 4 5 5 5 5 5
100 3 4 5 6 4 5 5 5 5 5
The First column and row i want to use as my variables. So for instance if i want to manipulate a certain region, how would I do so? e.g. all values between 5 - 15 (top row) and 20-41 (first column) were to be multiplied by 1.33.
Ideally, i want this to be used in a GUI but I want to get the concept understood first as i'm still a new user to the software.
Thanks for all the help,
Kind regards,
Sam

Build a logical index, using bsxfun to combine the row and column conditions (could also be done with repmat). Then use that index to apply the desired operation to the selected entries.
Let A denote your matrix:
ind = bsxfun(#and, A(1,:)>=5 & A(1,:)<=15, A(:,1)>=20 & A(:,1)<=41);
A(ind) = A(ind)*1.33;

You probably need to create some kind of lookup function or data structure. I would create two vectors for your first row and first column separately from your "data" matrix, and use find() function to look up the corresponding index.
If you know the indices of the values that you want to modify in your matrix, then,
A(3:6,2:4) = 1.33*A(3:6,2:4);
should work.

In this case I would actually use 2 indices, one for each dimension.
I assume your data is in one matrix but it should not be too hard to adjust for the case where you use 2 vectrices and a matrix.
idx1 = A(1,:)>=5 & A(1,:)<=15;
idx2 = A(:,1)>=20 & A(:,1)<=41);
A(idx1,idx2) = A(idx1,idx2)*1.33

Related

Take a column of a matrix and make it a row in kdb

Consider the matrix:
1 2 3
4 5 6
7 8 9
I'd like to take the middle column, assign it to a variable, and replace the middle row with it, giving me
1 2 3
2 5 8
7 8 9
I'm extracting the middle column using
a:m[;enlist1]
which returns
2
5
8
How do I replace the middle row with a? Is a flip necessary?
Thanks.
If you want to update the matrix in place you can use
q)show m:(3;3)#1+til 10
1 2 3
4 5 6
7 8 9
q)a:m[;1]
q)m[1]:a
q)show m
1 2 3
2 5 8
7 8 9
q)
cutting out "a" all you need is:
m[1]:m[;1]
You can use dot amend -
q)show m:(3;3)#1+til 10
1 2 3
4 5 6
7 8 9
q)show a:m[;1]
2 5 8
q).[m;(1;::);:;a]
1 2 3
2 5 8
7 8 9
Can see documentation here:
http://code.kx.com/wiki/Reference/DotSymbol
http://code.kx.com/wiki/JB:QforMortals2/functions#Functional_Forms_of_Amend
Making it slightly more generic where you can define the operation, row, and column
q)m:3 cut 1+til 9
1 2 3
4 5 6
7 8 9
Assigning the middle column to middle row :
q){[ m;o;i1;i2] .[m;enlist i1;o; flip[m] i2 ] }[m;:;1;1]
1 2 3
2 5 8
7 8 9
Adding the middle column to middle row by passing o as +
q){[ m;o;i1;i2] .[m;enlist i1;o; flip[m] i2 ] }[m;+;1;1]
1 2 3
6 10 14
7 8 9

MATLAB - generating vector with sequence of values

Given two parameters:
n %number of repetitions per value
k %max value to repeat
I would like to create a vector of size n*k, which is a concatenation of k vectors of size n, such that the i'th vector contains the value i at each coordinate.
Example:
n = 5;
k = 9;
Desired result:
[1,1,1,1,1,2,2,2,2,2,3,3,3,3,3,4,4,4,4,4,5,5,5,5,5,6,6,6,6,6,7,7,7,7,7,8,8,8,8,8,9,9,9,9,9];
Is there an elegant way to achieve this?
Thanks!
quite a few ways to do it:
method 1:
A=1:k
repelem(A',n,1)'
method 2:
A=1:k
kron(A', ones(n,1))'
method 3:
A=1:k
B=repmat(A, n, 1)
B(:)'
method 4:
A=1:k
B=ones(n,1)*A
B(:)'
Here is an alternative method
A = reshape(mtimes((1:k).',ones(1,n)).',1,n*k)
A =
Columns 1 through 22
1 1 1 1 1 2 2 2 2 2 3 3 3 3 3 4 4 4 4 4 5 5
Columns 23 through 44
5 5 5 6 6 6 6 6 7 7 7 7 7 8 8 8 8 8 9 9 9 9
Column 45
9
It multiplies each element by ones n times
>> mtimes((1:k).',ones(1,5)).'
ans =
1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9
and then reshapes the whole matrix to one vector

Extracting max value from each column in a table

I have generated a table of data with time in one column with attempts 1-10 in the next series of columns. I want to be able to extract the max value in each attempt for further analysis.
I have tried for table MGA
max = max(MGA(:, []))
I get the following error -- "You cannot subscript a table using only one subscript. Table subscripting requires both row and variable subscripts."
First off: Never do max = max();, you'll overload max, and you won't be able to use it again.
And to answer the question, you can do as follows (notice that I've kept the values in the first columns):
MGA
MGA =
1 5 3 8 9
2 4 7 3 3
3 8 7 6 9
4 8 2 7 3
5 2 2 9 10
6 5 5 10 4
7 5 10 6 2
8 7 4 2 3
9 8 6 2 7
10 8 3 3 5
max_values = [MGA(:,1), max(MGA(:,2:end),[],2)]
max_values =
1 9
2 7
3 9
4 8
5 10
6 10
7 10
8 7
9 8
10 8

Matlab: creating a matrix whose rows consist of a linspace or similar pattern

Anybody know a fast way to produce a matrix consisting of a linspace for each row? For example, the sort of pattern I'm looking for in this matrix is:
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
...
1 2 3 4 5 6 7 8 9 10
Anyone know any fast tricks to produce this WITHOUT using a for loop?
I just figured this out, so just in case anyone else was troubled by this, we can achieve this exact pattern by:
a=linspace(1,10,10);
b=ones(3,1)*a;
This will give:
>> a = 1 2 3 4 5 6 7 8 9 10
>> b = 1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
You need to use repmat.
Example:
>> B = repmat(1:10,[3 1])
B =
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
You can vary the value of 3 there. You can change it accordingly.
Another shortcut I can recommend is similar to repmat, but you specify a base array first of a = 1:10;. Once you do this, you specify a series of 1s in the first dimension when indexing which should produce a matrix of the same vectors with many rows as you want, where each row consists of the base array a. As such:
%// number of times to replicate
n = 4;
a = 1:10;
a = a(ones(1,n),:);
Result:
a =
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
Insert this command: transpose(ndgrid(1:10,1:n));, where n is the number of rows desired in the result.
You can consider these solutions:
With basic matrix indexing (taken from here)
b=a([1:size(a,1)]' * ones(1,NumToReplicate), :) %row-wise replication
b=a(:, ones(NumToReplicate, 1)) %column-wise replication
With bsxfun:
bsxfun(#times,a,(ones(1,NumToReplicate))') %row-wise replication
bsxfun(#times,a',(ones(1,NumToReplicate))) %column-wise replication
You are welcome to benchmark above two solutions with repmat.

MATLAB: Ignoring Specific Columns in a Matrix when Carrying Out a Loop

so far I have this:
for l=1:50
%# matrix of distances between terminal nodes, index of column represents
%# where the searcher is going from and the index of the row represents
%# where the searcher is going to
d = [
10 2 2 3 3 2 4 5 5 4 4 4 3 3 4 4;
10 10 2 5 5 4 6 7 7 6 6 6 5 5 6 6;
10 2 10 5 5 4 6 7 7 6 6 6 5 5 6 6;
10 5 5 10 2 3 7 8 8 7 7 7 6 6 7 7;
10 5 5 2 10 3 7 8 8 7 7 7 6 6 7 7;
10 4 4 3 3 10 6 7 7 6 6 6 5 5 6 6;
10 6 6 7 7 6 10 3 3 2 4 4 5 5 6 6;
10 7 7 8 8 7 3 10 2 3 5 5 6 6 7 7;
10 7 7 8 8 7 3 2 10 3 5 5 6 6 7 7;
10 6 6 7 7 6 2 3 3 10 4 4 5 5 6 6;
10 6 6 7 7 6 4 5 5 4 10 2 5 5 6 6;
10 6 6 7 7 6 4 5 5 4 2 10 5 5 6 6;
10 5 5 6 6 5 5 6 6 5 5 5 10 2 3 3;
10 5 5 6 6 5 5 6 6 5 5 5 2 10 3 3;
10 6 6 7 7 6 6 7 7 6 6 6 3 3 10 2;
10 6 6 7 7 6 6 7 7 6 6 6 3 3 2 10
];
i=1; %# start the searcher at the origin
h=5;
t=0; %# start time of the game
k=find(d(i,:)==min(d(i,:))); %# position closest nodes
j=randsample(k,1,true); %# randomly selects closest node if multiple nodes within closest distance
c=min(d(i,:));
while j~=h %# while the searcher is not in the same position as the hider
d(:,j)=[]; %# delete the column corresponding to the searchers position so he cannot return here
%# want to ignore all previous positions not delete them!
i=j; %# reset the searchers current position
k=find(d(i,:)==min(d(i,:))) %# find the new minimum distance
p=rand(1)*length(k); %# randomly select an index of k
q=floor(p)+1 %# take the integer part of k
j=k(q) %# randomly select from all the closest nodes
t=t+min(d(i,:))+c; %# calculate cumulative time for paths traveled
end
Found(l)=j-1 %# show position where the hider was found (relate matrix index to node index)
Time(l)=t %# show time taken for the searcher to find the hider
end
So the elements in d are the distance between two positions, represented by the row and column position, then the aim is to reach column 5 (h) by traveling the shortest distances between positions.
The problem I have is that I am currently deleting each column as it is searched for the minimum distance, this is then redefining the index of the column and so when h is either not being reached or it is not the correct h. How can I ignore rows already searched in the 'while' loop?
Any help will be gratefully received, thank you.
You can create an array flags=zeros(16,1) and turn flag(i)=1 when you visit the row. Then you can check whether a row was flagged.