I hope to gather last lines from each submatrix or cell arrays.
I have 17 x 20 cells in matrix name A.
Each submatrices have different number of lines, but same number of columns (total 7 columns, all)
I tried to generate a file, made up of only last rows of each submatrices. My target file's from will be
M = [column1 column2 column3 column4 column5 column6 column7]
% made up of last rows of each submatrices, unknown number of lines, 7 columns
So I tried
for x_cc = 1:20
for y_cc = 1:17
M = A{x_cc, y_cc}(end,:);
end
end
But it is not working, giving the error Subscript indices must either be real positive integers or logicals.
Should I need to define the size first? What operation should be done? or what commands are useful? I tried cellfun, but not sure how can I use here.
Need any help to solve this situation. Thanks~!
First off, it looks like you switched x_cc and y_cc. Since your matrix is 17 x 20, x_cc is the rows and should go to 17, while y_cc will go to 20.
However, the error you're getting is probably coming from trying to index an empty array (one of those contained in A) using end. An example of this error:
a = [];
a(end)
??? Subscript indices must either be real positive integers or logicals.
If you're curious, a method avoiding for loops would look like:
B = cellfun(#(x) x(end,:), A, 'UniformOutput', 0);
M = cell2mat(B(:));
This grabs the last row from each matrix in A, then stacks them vertically and transforms to an array.
Related
I need to know if there is any efficient way of doing the following in MATLAB.
I have several big sparse matrices, the size of each one is roughly 9000000x9000000.
I need to access multiple element of such matrix and assign to each selected element a different value stored in another array. I'll give an example:
What I have:
SPARSE MATRIX of size 9000000x9000000
Matrix with the list of indexes and values I want to access, this is a matrix like this:
[row1, col1, value1;
row2, col2, value2;
...
rowN, colN, valueN]
Where N is the length of such matrix.
What I need:
Assign to the SPARSE MATRIX the corresponding value to the corresponding index, this is:
SPARSE_MATRIX(row1, col1) = value1
SPARSE_MATRIX(row2, col2) = value2
...
SPARSE_MATRIX(rowN, colN) = valueN
Thanks in advance!
EDIT:
Thank you to both for answering, I think I did not explain myself well, I'll try again.
I already have a large SPARSE MATRIX of about 9000000 rows x 9000000 columns, it is a SPARSE MATRIX filled with zeros.
Then I have another array or matrix, let's call it M with N number of rows, where N could take values from 0 to 9000000; and 3 columns. The first two columns are used to index an element of my SPARSE MATRIX, and the third column stores the value I want to transfer to the SPARSE MATRIX, this is, given a random row of M, i:
SPARSE_MATRIX(M(i, 1), M(i, 2)) = M(i, 3)
The idea is to do that for all the rows, I have tried it with common indexing:
SPARSE_MATRIX(M(:, 1), M(:, 2)) = M(:, 3)
Now I would like to do this assignation for all the rows in M as fast as possible, because if I use a loop or common indexing it takes ages (I am using a 7th Gen i7 processor with 16 GB of RAM). And I also need to keep the zeros in the SPARSE_MATRIX.
EDIT 2: SOLVED! Thank you Metahominid, I was not thinking through, but yes the sparse function does solve my problem, I just think my brain circuits were shortcircuited yesterday and was unable to see through it hahaha. Thank you to both anyway!
Regards!
You can construct a sparse matrix like this.
A = sparse(i,j,v)
S = sparse(i,j,v) generates a sparse matrix S from the triplets i, j,
and v such that S(i(k),j(k)) = v(k). The max(i)-by-max(j) output
matrix has space allotted for length(v) nonzero elements. sparse adds
together elements in v that have duplicate subscripts in i and j.
So you can simply construct the row vector, column vector and value vector.
I am answering in part because I cannot comment. You question seems a little confusing to me. The sparse() function in MATLAB does just this.
You can enter your arrays of indices and values directly into the interface, or declare a sparse matrix of zeros and set each individually.
Given your data format make three vectors, ROWS = [row1; ...; rown], COLS = [col1; ...; coln], and DATA = [val1; ... valn]. I am assuming that your size is the overall size of the full matrix and not the sparse portion.
Then
A = sparse(ROWS, COLS, DATA) will do just what you want. You can even specify the original matrix size.
A = sparse(ROWS, COLS, DATA, 90...., 90....).
I have a column vector A with dimensions (35064x1) that I want to reshape into a matrix with 720 lines and as many columns as it needs.
In MATLAB, it'd be something like this:
B = reshape(A,720,[])
in which B is my new matrix.
However, if I divide 35604 by 720, there'll be a remainder.
Ideally, MATLAB would go about filling every column with 720 values until the last column, which wouldn't have 720 values; rather, 504 values (48x720+504 = 35064).
Is there any function, as reshape, that would perform this task?
Since I am not good at coding, I'd resort to built-in functions first before going into programming.
reshape preserves the number of elements but you achieve the same in two steps
b=zeros(720*ceil(35604/720),1); b(1:35604)=a;
reshape(b,720,[])
A = rand(35064,1);
NoCols = 720;
tmp = mod(numel(A),NoCols ); % get the remainder
tmp2 = NoCols -tmp;
B = reshape([A; nan(tmp2,1)],720,[]); % reshape the extended column
This first gets the remainder after division, and then subtract that from the number of columns to find the amount of missing values. Then create an array with nan (or zeros, whichever suits your purpose best) to pad the original and then reshape. One liner:
A = rand(35064,1);
NoCols = 720;
B = reshape([A; nan(NoCols-mod(numel(A),NoCols);,1)],720,[]);
karakfa got the right idea, but some error in his code.
Fixing the errors and slightly simplifying it, you end up with:
B=nan(720,ceil(numel(a)/720));
B(1:numel(A))=A;
Create a matrix where A fits in and assingn the elemnent of A to the first numel(A) elements of the matrix.
An alternative implementation which is probably a bit faster but manipulates your variable b
%pads zeros at the end
A(720*ceil(numel(A)/720))=0;
%reshape
B=reshape(A,720,[]);
I have a matrix of 0s, 1s, 2s and 3s.If all the elements in the same row are the same then I want it to display the text 'flush'. For example, I have the matrix
[0,1,0,2,3;
0,0,0,0,0;
3,2,1,3,1;
2,2,2,2,2];
How would I program Matlab to recognise the 2nd and 4th row all have the same number?
A = [0,1,0,2,3; 0,0,0,0,0; 3,2,1,3,1; 2,2,2,2,2]
As it was said before if you only have positive numbers you can use the variance.
n_flush = var(A, [], 2) == 0
However, this will fail for negative numbers for example a row like [-2 -1 1 2].
What I would do is to compare the first column with the rest and flag the rows where all the elements are equal.
n_flush = all(bsxfun(#eq, A(:,1), A(:,2:end)),2)
Now, if you want to display flush every time the rows are equal you can do
for ind = find(n_flush)
fprintf('flush row %i\n', ind)
end
If you need to have the whole thing in a one-liner (which is what many Matlab-geeks try to do), then maybe this here will suit your needs
cellfun(#(x) char((x==0)*sprintf('flush')), num2cell(var(A')'), 'UniformOutput', false)
Edit: nice idea GameOfThrows
Yet another solution by explicitly subtracting the first column from each column via duplicating the first column to other columns of a matching-sized matrix.
identical_rows = ~any(A - kron(ones(1,size(A,2)),A(:,1)),2)
Sorry for the title. I could not think of something better.
I have the following problem.
I have two four-column matrices build up like this:
Property | X | Y | Z
The two matrices have different sizes, since matrix 1 has a large amount of additional rows compared to matrix 2.
What I want to do is the following:
I need to create a third matrix that only features those rows (of the large matrix) that are identical in columns X, Y and Z to rows in matrix2(the property column is always different).
I tried an if-statement but it did not really work out due to my programming syntax. Has somebody a tip?
Thank you!
I tried something like this: (in this case A is the larger matrix and I want its property column for X,Y,Z-positions that are identical to another matrix B.. I am terrible with the MatLab-syntax..
if (A(:,2) == B(:,2) and (A(:,3) == B(:,3) and (A(:,4) == B(:,4))
newArray(:,1) = A(:,1);
end
Use ismember with the 'rows' option to find the desired rows, and then use that as an index to build the result:
ind = ismember(A(:,2:4), B(:,2:4), 'rows');
C = A(ind,:);
I have assumed that a row of A is selected if its last three columns match those of any row of B.
Hi I have problem with matrix..
I have many .txt files with different number of rows but have the same number of column (1 column)
e.g. s1.txt = 1234 rows
s2.txt = 1200 rows
s2.txt = 1100 rows
I wanted to combine the three files. Since its have different rows .. when I write it to a new file I got this error = Index exceeds matrix dimensions.
How I can solved this problem? .
You can combine three matrices simply by stacking them: Assuming that s1, etc are the matrices you read in, you can make a new one like this:
snew = [s1; s2; s3];
You could also use the [] style stacking without creating the new matrix variable if you only need to do it once.
You have provided far too little information for an accurate diagnosis of your problem. Perhaps you have loaded the data from your files into variables in your workspace. Perhaps s1 has 1 column and 1234 rows, etc. Then you can concatenate the variables into one column vector like this:
totalVector = [s1; s2; s3];
and write it out to a file with a save() statement.
Does that help ?
Let me make an assumption that this question is connecting with your another question, and you want to combine those matrices by columns, leaving empty values in columns with fewer data.
In this case this code should work:
BaseFile ='s';
n=3;
A = cell(1,n);
for k=1:n
A{k} = dlmread([BaseFile num2str(k) '.txt']);
end
% create cell array with maximum number of rows and n number of columns
B = cell(max(cellfun(#numel,A)),n);
% convert each matrix in A to cell array and store in B
for k=1:n
B(1:numel(A{k}),k) = num2cell(A{k});
end
% save the data
xlswrite('output.txt',B)
The code assumes you have one column in each file, otherwise it will not work.