Multiply a column by a scalar in MATLAB - matlab

I have a N X 2 matrix which I would like to multiply the second column by a certain number.
The matrix looks like this:
1 0
6 0
7 0
8 0
4 0.0173000000000000
5 0.0269000000000000
3 0.0720000000000000
2 0.883800000000000
But I would like to multiply just the second column by a certain number without affecting the first column. How do I do that in MATLAB?

a(:, 2) = a(:,2)*2
where a is your matrix.

Related

Inserting columns to a matrix in Matlab

I'd like to insert columns to a matrix, but the insertion column positions within the matrix differ by row. How can I do this without using for-loop?
Following is a simplified example in MATLAB;
From A,X,P, I want to get APX without using for-loop.
>> A = zeros(4,5) % inclusive matrix
A =
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
>> X = [9,8;5,7;8,3;6,7] % data to insert
X =
9 8
5 7
8 3
6 7
>> P = [3;2;4;1] % insertion position within the matrix
P =
3
2
4
1
>> APX = [0,0,9,8,0;0,5,7,0,0;0,0,0,8,3;6,7,0,0,0] % what I want
APX =
0 0 9 8 0
0 5 7 0 0
0 0 0 8 3
6 7 0 0 0
It's simply determining the right column-major indices to access the matrix so you can populate it with your desired values. This first requires generating the right row and column values to access the right positions in APX so you can use X to populate those positions.
Using P, each element tells you which column you should start populating for each row of X. You will need to generate column indices in increasing order up to as many columns as there are in X. To generate the row indices, simply create a matrix that is the same size as X where each column spans from 0 up to as many rows as there are in X minus 1 (i.e. 0:size(X,2)-1). This matrix gives you the correct offsets so that you can take P and add it with this matrix. Once you do that you will have a column index matrix that tells you specifically where each element should go with regards to the columns of the output matrix per row of P. Finally, use sub2ind to generate the column-major indices using the rows and columns generated above to place X in APX.
In other words:
P = [3;2;4;1];
X = [9,8;5,7;8,3;6,7];
rowInd = repmat((1:size(X,1)).', 1, size(X,2)); %'
colInd = bsxfun(#plus, P, 0:size(X,2)-1);
APX = zeros(size(X,1), max(colInd(:)));
APX(sub2ind(size(APX), rowInd, colInd)) = X;
To generate the row locations, we use repmat to create a matrix that is the same size as X where each column spans from 1 up to as many rows as X. To generate the column locations, we use bsxfun to create a matrix where each column is the vector P but increasing by 1 per column. We then create APX to be of compatible size then use sub2ind to finally populate the matrix.
With your above test inputs, we get:
APX =
0 0 9 8 0
0 5 7 0 0
0 0 0 8 3
6 7 0 0 0
Minor Note
You really should actually try using loops before trying it vectorized. Though using loops was slow in previous versions of MATLAB, MATLAB R2015b has an improved JIT engine where loops are now competitive. You should time your code using loops and ensuring that it is justifiable before switching to vectorized implementations.

How to count patterns columnwise in Matlab?

I have a matrix S in Matlab that looks like the following:
2 2 1 2
2 3 1 1
3 3 1 1
3 4 1 1
3 1 2 1
4 1 3 1
1 1 3 1
I would like to count patterns of values column-wise. I am interested into the frequency of the numbers that follow right after number 3 in any of the columns. For instance, number 3 occurs three times in the first column. The first time we observe it, it is followed by 3, the second time it is followed by 3 again and the third time it is followed by 4. Thus, the frequency for the patters observed in the first column would look like:
3-3: 66.66%
3-4: 33.33%
3-1: 0%
3-2: 0%
To generate the output, you could use the convenient tabulate
S = [
2 2 1 2
2 3 1 1
3 3 1 1
3 4 1 1
3 1 2 1
4 1 3 1
1 1 3 1];
idx = find(S(1:end-1,:)==3);
S2 = S(2:end,:);
tabulate(S2(idx))
Value Count Percent
1 0 0.00%
2 0 0.00%
3 4 66.67%
4 2 33.33%
Here's one approach, finding the 3's then looking at the following digits
[i,j]=find(S==3);
k=i+1<=size(S,1);
T=S(sub2ind(size(S),i(k)+1,j(k))) %// the elements of S that are just below a 3
R=arrayfun(#(x) sum(T==x)./sum(k),1:max(S(:))).' %// get the number of probability of each digit
I'm going to restate your problem statement in a way that I can understand and my solution will reflect this new problem statement.
For a particular column, locate the locations that contain the number 3.
Look at the row immediately below these locations and look at the values at these locations
Take these values and tally up the total number of occurrences found.
Repeat these for all of the columns and update the tally, then determine the percentage of occurrences for the values.
We can do this by the following:
A = [2 2 1 2
2 3 1 1
3 3 1 1
3 4 1 1
3 1 2 1
4 1 3 1
1 1 3 1]; %// Define your matrix
[row,col] = find(A(1:end-1,:) == 3);
vals = A(sub2ind(size(A), row+1, col));
h = 100*accumarray(vals, 1) / numel(vals)
h =
0
0
66.6667
33.3333
Let's go through the above code slowly. The first few lines define your example matrix A. Next, we take a look at all of the rows except for the last row of your matrix and see where the number 3 is located with find. We skip the last row because we want to be sure we are within the bounds of your matrix. If there is a number 3 located at the last row, we would have undefined behaviour if we tried to check the values below the last because there's nothing there!
Once we do this, we take a look at those values in the matrix that are 1 row beneath those that have the number 3. We use sub2ind to help us facilitate this. Next, we use these values and tally them up using accumarray then normalize them by the total sum of the tallying into percentages.
The result would be a 4 element array that displays the percentages encountered per number.
To double check, if we look at the matrix, we see that the value of 3 follows other values of 3 for a total of 4 times - first column, row 3, row 4, second column, row 2 and third column, row 6. The value of 4 follows the value of 3 two times: first column, row 6, second column, row 3.
In total, we have 6 numbers we counted, and so dividing by 6 gives us 4/6 or 66.67% for number 3 and 2/6 or 33.33% for number 4.
If I got the problem statement correctly, you could efficiently implement this with MATLAB's logical indexing and an approach that is essentially of two lines -
%// Input 2D matrix
S = [
2 2 1 2
2 3 1 1
3 3 1 1
3 4 1 1
3 1 2 1
4 1 3 1
1 1 3 1]
Labels = [1:4]'; %//'# Label array
counts = histc(S([false(1,size(S,2)) ; S(1:end-1,:) == 3]),Labels)
Percentages = 100*counts./sum(counts)
Verify/Present results
The styles for presenting the output results listed next use MATLAB's table for a well human-readable format of data.
Style #1
>> table(Labels,Percentages)
ans =
Labels Percentages
______ ___________
1 0
2 0
3 66.667
4 33.333
Style #2
You can do some fancy string operations to present the results in a more "representative" manner -
>> Labels_3 = strcat('3-',cellstr(num2str(Labels','%1d')'));
>> table(Labels_3,Percentages)
ans =
Labels_3 Percentages
________ ___________
'3-1' 0
'3-2' 0
'3-3' 66.667
'3-4' 33.333
Style #3
If you want to present them in descending sorted manner based on the percentages as listed in the expected output section of the question, you can do so with an additional step using sort -
>> [Percentages,idx] = sort(Percentages,'descend');
>> Labels_3 = strcat('3-',cellstr(num2str(Labels(idx)','%1d')'));
>> table(Labels_3,Percentages)
ans =
Labels_3 Percentages
________ ___________
'3-3' 66.667
'3-4' 33.333
'3-1' 0
'3-2' 0
Bonus Stuff: Finding frequency (counts) for all cases
Now, let's suppose you would like repeat this process for say 1, 2 and 4 as well, i.e. find occurrences after 1, 2 and 4 respectively. In that case, you can iterate the above steps for all cases and for the same you can use arrayfun -
%// Get counts
C = cell2mat(arrayfun(#(n) histc(S([false(1,size(S,2)) ; S(1:end-1,:) == n]),...
1:4),1:4,'Uni',0))
%// Get percentages
Percentages = 100*bsxfun(#rdivide, C, sum(C,1))
Giving us -
Percentages =
90.9091 20.0000 0 100.0000
9.0909 20.0000 0 0
0 60.0000 66.6667 0
0 0 33.3333 0
Thus, in Percentages, the first column are the counts of [1,2,3,4] that occur right after there is a 1 somewhere in the input matrix. As as an example, one can see column -3 of Percentages is what you had in the sample output when looking for elements right after 3 in the input matrix.
If you want to compute frequencies independently for each column:
S = [2 2 1 2
2 3 1 1
3 3 1 1
3 4 1 1
3 1 2 1
4 1 3 1
1 1 3 1]; %// data: matrix
N = 3; %// data: number
r = max(S(:));
[R, C] = size(S);
[ii, jj] = find(S(1:end-1,:)==N); %// step 1
count = full(sparse(S(ii+1+(jj-1)*R), jj, 1, r, C)); %// step 2
result = bsxfun(#rdivide, count, sum(S(1:end-1,:)==N)); %// step 3
This works as follows:
find is first applied to determine row and col indices of occurrences of N in S except its last row.
The values in the entries right below the indices of step 1 are accumulated for each column, in variable count. The very convenient sparse function is used for this purpose. Note that this uses linear indexing into S.
To obtain the frequencies for each column, count is divided (with bsxfun) by the number of occurrences of N in each column.
The result in this example is
result =
0 0 0 NaN
0 0 0 NaN
0.6667 0.5000 1.0000 NaN
0.3333 0.5000 0 NaN
Note that the last column correctly contains NaNs because the frequency of the sought patterns is undefined for that column.

Selecting elements in matrix using matlab

My problem is this: I've a matrix, as example
1 2 3
4 2 6
6 1 8
4 5 4
7 1 5
8 2 0
I wish to extract selected values from the matrix, as example, a vector like this
B = [3 6 0]
selecting third column values when the value in the second column is 2.
I tried in different ways, but no one of these works.
Use this -
B = A(A(:,2)==2,3)' %// Assuming A is your input matrix
If M is your Matrix, you can select the second column using
M(:,2)
Compare it to two to get the lines which contain a 2
M(:,2)==2
And use this logical vector to select your elements from the third column.
M(M(:,2)==2,3)
A little more generally: if you want to select based on a set of values, use ismember to generate the logical index:
>> A(ismember(A(:,2), [2 5]) , 3) %// [2 5]: values you want to find in 2nd col
ans =
3
4
6
0

In a 100 X 2 matrix, how do divide each element in column 2 by a constant?

I have a 100 by 2 matrix. And I'm trying to figure out how to divide all terms in the second column by a constant.
For example, let's say I have this matrix.
[1 2;
3 4;
5 6]
I want to divide the 2nd column by 2.
[1 2/2;
3 4/2;
5 6/2]
So my final matrix will be.
[1 1;
3 2;
5 3]
Thank you.
If your matrix is M then:
M(:,2)=M(:,2)./2;
will divide all terms in the second column by a constant (2). By the way, because the value you divide with is a constant you can also write / instead of ./
If you'd like to assemble a new matrix and not overwrite the first one just write something like this:
A=[M(:,1) M(:,2)./2]
I'm not sure how natan 's equations should be read, but I'd multiply the first matrix
1 2
3 4
5 6
by the matrix
1 0
0 .5
The resulting matrix is
1 1
3 2
5 3

How to combine vectors of different length in a cell array into matrix in MATLAB

How to efficiently combined cell array vectors with different length into a matrix, filling the vectors to max length with 0s or NaNs? It would be a nice option for cell2mat().
For example, if I have
C = {1:3; 1:5; 1:4};
I'd like to get either
M = [1 2 3 0 0
1 2 3 4 5
1 2 3 4 0];
or
M = [1 2 3 NaN NaN
1 2 3 4 5
1 2 3 4 NaN];
EDIT:
For a cell of row vectors as in your case, this will pad vectors with zeros to form a matrix
out=cell2mat(cellfun(#(x)cat(2,x,zeros(1,maxLength-length(x))),C,'UniformOutput',false))
out =
1 2 3 0 0
1 2 3 4 5
1 2 3 4 0
A similar question was asked earlier today, and although the question was worded slightly differently, my answer basically does what you want.
Copying the relevant parts here, a cell of uneven column vectors can be zero padded into a matrix as:
out=cell2mat(cellfun(#(x)cat(1,x,zeros(maxLength-length(x),1)),C,'UniformOutput',false));
where maxLength is assumed to be known. In your case, you have row vectors, which is just a slight modification from this.
If maxLength is not known, you can get it as
maxLength=max(cellfun(#(x)numel(x),C));