My matrix currently looks like this
1 225 230 300
4 333 442 678
7 798 782 128
1 248 842 482
Coloumn 1 is a series of numbers which I have mapped to another set of numbers.
for example
KeySet = (1:42)
ValueSet = (333, 222, 4444, 7778 etc etc to 42 numbers)
mapObj = containers.Map(KeySet, ValueSet)
Now I want to create a new coloumn in my original matrix coloumn 5 which will be populated from the ValueSet with reference to the mapping - so row 1 coloumn 5 will be 333 and row 2 coloumn 5 will be 7778 and so on.
Its essentially a vlookup from coloumn 5 into the mapping.
It would look something like this I would guess
mat(:,5) = mapObj(mat(:,1))
You can't query a mapobject for multiple entries at once, i would use arrayfun:
arrayfun(#(ix)mapObj(ix),mat(:,1))
In your example the key set is 1:n, if this is always the case then use an array instead of a map, it's much faster and you can index multiple entries at once.
Related
Say I have a matrix, M:
9.89E+10 3.12E+10 29
8.88E+10 8.16E+10 9
9.97E+10 8.31E+10 22
8.10E+10 6.55E+10 94
2.17E+10 8.11E+09 53
6.34E+10 8.84E+10 54
5.69E+10 7.07E+10 8
9.23E+10 8.24E+10 38
8.88E+10 5.81E+10 27
And I have another array, A:
A=8.88E+10, 9.23E+10
I want all the entries in M that contain all the entries in A. That is, my output should be a matrix, N:
8.88E+10 8.16E+10 9
9.23E+10 8.24E+10 38
8.88E+10 5.81E+10 27
I can do this using a code like:
count=1;
for i=1:size(A,1)
for j=1:size(M,1)
if M(j,1)==A(i,1)
extracted(count,:)=M(j,:);
count=count+1;
end
end
end
But I guess there could be a one liner code in MATLAB to do this. Is there any?
One Liner Solution
N = M(sum(ismember(M,A),2)>0,:);
Explanation
The ismember function generates a binary matrix of the same size of M, which contains 1 for each value in M which exists in A and 0 otherwise.
We use sum function to sum each row in that matrix. rows which sum up to a value which is bigger than 0 are rows which contains values from A.
Last, we generate the out matrix by taking all the rows from M which fits to the constraint from previous stage.
Result
N =
8.88E+10 8.16E+10 9
9.23E+10 8.24E+10 38
8.88E+10 5.81E+10 27
I want to insert a number in the following matrix: n x 1 matrix
6
103
104
660
579
750
300
299
300
750
579
661
580
760
302
301
302
760
580
662
581
How to I insert it in the middle and shift the remaining numbers? I tried the following code:
Idx=[723];
c=false(1,length(Element_set2)+length(Idx));
c(Idx)=true;
result=nan(size(c));
result(~c)=Element_set2;
result(c)=8
You are complicating things. Simply find the middle index by finding the length of the array, dividing by 2 and truncating any decimal points, then using simply indexing to update the new matrix. Supposing that result is the column vector that was created by you and number is the value you want to insert in the middle, do the following:
number = 8; %// Change to suit whatever number you desire
middle = floor(numel(result) / 2);
result = [result(1:middle); number; result(middle+1:end)];
In the future, please read this great MATLAB tutorial on indexing directly from MathWorks: http://www.mathworks.com/company/newsletters/articles/matrix-indexing-in-matlab.html. It's a good resource on the kinds of indexing operations one expects from starting out in MATLAB.
I have data of integers in x = 500 X 612 matrix. I need a new variable xx in a 500 X 612 matrix but I need to apply cumsum along each row (500) across 12 column steps and applying cumsum like this 51 times --> 500 X (12 X 51) matrix. Then I need a for loop to produce 51 plots of the 500 rows and 12 columns of the cumsum time series. thank you!
I will rephrase what the question is asking to benefit those who are reading.
The OP wishes to segment a matrix into chunks by splitting up the matrix into a bunch of columns. A cumsum is applied to each row individually for each column and are then concatenated together to build a final matrix. As such, given this source matrix:
x =
1 2 3 4 5 6 7 8 9 10 11 12
13 14 15 16 17 18 19 20 21 22 23 24
Supposing that we wish to split up the matrix by columns 3, 6 and 9 and 12, we will have four chunks to work with. We do a cumsum on each of these blocks individually and piece the final result together. So the result would like the following:
xx =
1 3 6 4 9 15 7 15 24 10 21 33
13 27 42 16 33 51 19 39 60 22 45 69
First, you need to determine how many columns you want to break up the matrix into. In your case, we wish to segment the matrix into 4 chunks: Columns 1 - 3, columns 4 - 6, columns 7 - 9, and columns 10 - 12. As such, I'm going to reshape this matrix so that each column is an individual row from a chunk in this matrix. We then apply cumsum over this reshaped matrix and we then reshape it back to what you had originally.
Therefore, do this:
num_chunks = 4; %// Columns 3, 6, 9, 12
divide_point = size(x,2) / num_chunks; %// Determine how many elements are in a row for a cumsum
x_reshape = reshape(x.', divide_point, []); %// Get reshaped matrix
xy = cumsum(x_reshape); %// cumsum over all columns individually
xx = reshape(xy, size(x,2), size(x,1)).'; %// Reconstruct matrix
In the third line of code, x_reshape = reshape(x.', divide_point, []); may seem a bit daunting, but it's actually not that bad. I had to transpose the matrix first because you want to take each row of a chunk and place them into individual columns so we can perform a cumsum on each column. When you reshape something in MATLAB, it collects values column-wise and reshapes the input into an output of a specified size. Therefore, to collect the rows, we need to collect row-wise and so we must transpose this matrix. Next, divide_point tells you how many elements we have for a single row in one chunk. As such, we want to construct a matrix that is of size divide_point x N where divide_point tells you how many elements we have in a row of a chunk and N is the total number of rows over all chunks. Because I don't want to calculate how many there are (am rather lazy actually....), the [] syntax is to automatically infer this number so that we can get a reshaped matrix that respects the total number of elements in the original input. We then perform cumsum on each of these columns, and then we need to reshape this back into the original shape of the input. With this, we use reshape again on the cumsum result, but in order to get it back into the row-order that you want, we have to determine the transpose as reshape takes values in column-major order, then re-transpose that result.
We get:
xx =
1 3 6 4 9 15 7 15 24 10 21 33
13 27 42 16 33 51 19 39 60 22 45 69
In general, the total number of elements to sum over for a row needs to be evenly divisible by the total number of columns that your matrix contains. For example, given the above, if you were to try to segment this matrix into 5 chunks, you would certainly get an error as the number of rows to cumsum over is not symmetric.
As another example, let's say we wanted to break up the matrix into 6 chunks. Therefore, by setting num_chunks = 6, we get:
xx =
1 3 3 7 5 11 7 15 9 19 11 23
13 27 15 31 17 35 19 39 21 43 23 47
You can see that cumsum restarts at every second column, as we desired 6 chunks and to get 6 chunks with a matrix of 12 columns, a chunk is created at every second column.
This question is an outgrowth of MatLab (or any other language) to convert a matrix or a csv to put 2nd column values to the same row if 1st column value is the same?
If
A = [2 3 234 ; 2 44 33; 2 12 22; 3 123 99; 3 1232 45; 5 224 57]
1st column | 2nd column | 3rd column
2 3 234
2 44 33
2 12 22
3 123 99
3 1232 45
5 224 57
then running
[U ix iu] = unique(A(:,1) );
r= accumarray( iu, A(:,2:3), [], #(x) {x'} )
will show me the error
Error using accumarray
Second input VAL must be a vector with one element for each row in SUBS, or a
scalar.
I want to make
1st col | 2nd col | 3rd col | 4th col | 5th col | 6th col| 7th col
2 3 234 44 33 12 22
3 123 99 1232 45
5 224 57
I know how to do it using for and if, but that spends too much time for big data.
How can I do this?
Thank you in advance!
You're misusing accumarray in the solution provided to your previous question. The first parameter iu is the vector of indices and the second parameter should be a vector of values, of the same length. What you did here is specify a matrix as the second parameter, which in fact has twice more values than indices in iu.
What you need to do in order to make it work is create a vector of indices both for the second column and for the third column (they are the same indices, not coincidentally!) and specify a matching column vector of values, like so:
[U, ix, iu] = unique(A(:,1));
vals = reshape(A(:, 2:end).', [], 1); %'// Columnize values
subs = reshape(iu(:, ones(size(A, 2) - 1, 1)).', [], 1); %'// Replicate indices
r = accumarray(subs, vals, [], #(x){x'});
This solution is generalized for any number of columns that you want to pass to accumarray.
I have a challenge to order my matrix. The provided functions like sortrows work in the opposite way...
Take this 2D matrix
M =
40 45 68
50 65 58
60 55 48
57 67 44
,
The objective is to find matrix O that indicates the sorting index (rank) per row, i.e.:
O =
1 2 3
1 3 2
3 2 1
2 3 1
.
So for the second row 50 is the smallest element (1), 65 the largest (3), and 58 is the second largest (2), therefore row vector [1 3 2].
[~,sorted_inds] = sort(M,2);
will do.
I think you're looking for the second output of the regular sort function:
[~,I] = sort(M,2)
This syntax supresses the actual sorted matrix Msorted, and returns the indices I such that
for j = 1:n, Msorted(j,:) = M(I(j,:),j); end
Type doc sort for more information.