hi let's assume i have the following in matlab
h = [0,0,0,1;
1,1,1,1];
now how can i print all the values of the first subarray, i.e. 0,0,0,1
or for example the second subarray 1,1,1,1. thanks !
You can access just the first row of your matrix by doing
firstRow = h(1,:)
Similarly, you could access just the third column by
thirdColumn = h(:,3)
I suggest you look into the MATLAB help under "Matrix Indexing" as this is really basic stuff (and there's a lot of other nifty things you can do to access a subset of a matrix)
For printing, you can omit the final ;, or look into functions display and fprintf.
Related
I've hit some unexpected behaviour using the fprintf() function in MATLAB. I'm trying to print a multi-line file using the contents of a cell array and a numerical array. I know that I can use the fprintf() function as follows to print out the contents of a cell array:
myCellArray = {'one','two','three'};
fprintf('%s\n',myCellArray{:})
This results in the following output:
one
two
three
I can also print out a numerical array as follows:
myNumericalArray = [1,2,3];
fprintf('%i\n',myNumericalArray)
This results in:
1
2
3
However, the weird behaviour appears if I try to mix these, as follows:
fprintf('%s is %i\n',myCellArray{:},myNumericalArray)
This results in:
one is 116
wo is 116
hree is 1
I think this happens because MATLAB tries to print the next entry in myCellArray in the place of the %i, rather than using the first entry in myNumericalArray. This is evident if I type the following:
fprintf('%s %s\n',myCellArray{:},myCellArray{:})
Which results in:
one two
three one
two three
...Is there some way to ensure that only one element from each array is used per line?
I agree with your idea. So, I could only think of circumventing this by creating a combined cell array with alternating values from your two initial arrays, see the following code:
myCombinedArray = [myCellArray; mat2cell(myNumericalArray, 1, ones(1, numel(myNumericalArray)))];
fprintf('%s is %i\n', myCombinedArray{:})
Gives the (I assume) desired output:
one is 1
two is 2
three is 3
fprintf(formatSpec,A1,...,An) will print all the element of A1 in column order, then all the element of A2 in column order... and size(A1) is not necessarily equal to size(A2).
So in your case the easiest solution is IMO the for loop:
for ii = 1:length(myCellArray)
fprintf('%s is %d\n',myCellArray{ii},myNumericalArray(ii))
end
For the small explanation foo(cell{:}) is similar to the splat operator (python, ruby,...) so matlab will interpret this command as foo(cell{1},cell{2},...,cell{n}) and this is why your two arguments are not interpreted pair-wise.
This is similar to the loop solution, only more compact:
arrayfun(#(c,n) fprintf('%s is %i\n', c{1}, n), myCellArray, myNumericalArray)
I am a beginner in Matlab and have not been able to find an answer to my question so far. Your help will definitely be very much appreciated.
I have 70 matrices (100x100), named SUBJ_1, SUBJ_2 etc. I would like to create a loop so that I would calculate some metrics (i.e. max and min values) for each matrix, and save the output in a 70x2 result matrix (where each row would correspond to the consecutively named SUBJ_ matrix).
I am struggling with both stages - how to use the names of individual variables in a 'for' loop and how to properly save individual outputs in a combined array.
Many thanks and all the best!
Don't use such variable names, create a big cell array named SUBJ and put each Matrix in it.
r=zeros(numel(SUBJ),2)
for idx=1:numel(SUBJ)
r(idx,1)=min(min(SUBJ{idx}))
r(idx,2)=max(max(SUBJ{idx}))
end
min and max are called twice because first call creates maximum among rows, second call among columns.
Even though this is in principle possible in Matlab, I would not recommend it: too slow and cumbersome to implement.
You could instead use a 3-D matrix (100x100x70) SUBJ which would contain all the SUBJ_1 etc. in one matrix. This would allow you to calculate min/max etc. with just one line of code. Matlab will take care of the loops internally:
OUTPUT(:,1) = min(min(SUBJ,[],1)[],2);
OUTPUT(:,2) = max(max(SUBJ,[],1)[],2);
Like this, OUTPUT(1,1) contains min(min(SUBJ(:,:,1))) and so on...
As to how to use the names of individual variables in a 'for' loop, here gives an example:
SUBJ = [];
for idx = 1:70
term = eval(['SUBJ_',num2str(idx)]);
SUBJ = [SUBJ; max(max(term)),min(min(term))];
end
I have imported a lot of data from an excel spreadsheet so that I have a 1x27 matrix.
I have imported data from excel using this
filename = 'for_matlab.xlsx';
sheet = 27;
xlRange = 'A1:G6';
all_data = {};
for i=1:sheet,
all_data{i} = xlsread(filename, i, xlRange);
end
However each element of this all_data matrix (which is 1x27) contains my data but I'm having trouble accessing individual elements.
i.e.
all_data{1}
Will give me the entire matrix but I need to perform multiplications on individual elements of this data
also
all_data(1)
just gives '5x6 double', i.e. the matrix dimensions.
Does anybody know how I can divide all elements of each row by the third element in each row and do this for all of my 'sub-matrices' (for want of a better word)
Assuming that all_data is a cell array and that each cell contains a matrix (with at least three columns):
result = cellfun(#(x) bsxfun(#rdivide, x, x(:,3)), all_data, 'uniformoutput', 0);
You are mixing terminology in matlab. what you have is 1x27 CELLS each of them containing a matrix.
If you access all_data{1} it will give you the whole matrix stored in the first cell.
If you want to access the elemets of that matrix then you need to do: all_data{1}(2,4). This example access the 2,4 element of the matrix in the first cell.
Definitely Luis Mendo has solved you problem, but be aware of the differences of Cells and matrixes in Matlab!
Okay I have found the answer now.
Basically you have to use both types of brackets because the data types are different
i.e. all_data{1}(1:4) or something like that anyway.
Cheers
capi = cell2mat(arrayfun(#(b) sum(resulti == b,1),nonzeros(unique(resulti)), 'UniformOutput', false))
why when I used that code, my code cannot run and there was command like the following command?
??? Array dimensions must match for binary array op.
All this can be found via Matlab's documentation, which should always be your first step!
Having said that, here's a breakdown of your command:
cell2mat: convert a cell array to a matrix according to some format you define
arrayfun: evaluate some function for all elements in an array. The function may be an anonymous function (e.g., #(b) sum(resulti == b,1))
sum: sum all the elements of a matrix in a particular direction. Direction 1: down the rows, direction 2: along the columns, etc.
nonzeros: form new array by removing all zeros from the input array. This will output a column vector, irrespective of the input's shape.
unique: return the input array with all duplicates of all values removed. The output will also be sorted.
Type help [command] or doc [command] for more information on all these commands (which I recommend you do!)
Now, combining these into your command:
A = nonzeros(unique(resulti))
will return all unique entries in a column vector, with any zero removed.
B = arrayfun(#(b)sum(resulti==b), A, 'UniformOutput', false)
will run the function #(b) sum(resulti == b,1) on all entries of the newly created column vector A, and collect them in a cell-array B (cell, because 'UniformOutput' is set to false). This function will simply compare each element of resulti against the running index b, and find the total count along the rows. Then, finally,
capi = cell2mat(B)
will convert the cell-array B back to a normal Matlab array.
The objective of this command seems to be to count the number of non-unique occurrences on each of the colums of resulti. As hinted at by #GuntherStruyf, this whole command seems a hacked-together, forced one-liner, rather than well-manageable, readable code. I would personally opt to break it over several lines, avoid arrayfun (slow) and instead use bsxfun or a for-loop (faster (yes, also the for-loop), better readable).
But that's a matter of opinion (which goes against popular opinion :)
I want to apply a function to all columns in a matrix with MATLAB. For example, I'd like to be able to call smooth on every column of a matrix, instead of having smooth treat the matrix as a vector (which is the default behaviour if you call smooth(matrix)).
I'm sure there must be a more idiomatic way to do this, but I can't find it, so I've defined a map_column function:
function result = map_column(m, func)
result = m;
for col = 1:size(m,2)
result(:,col) = func(m(:,col));
end
end
which I can call with:
smoothed = map_column(input, #(c) (smooth(c, 9)));
Is there anything wrong with this code? How could I improve it?
The MATLAB "for" statement actually loops over the columns of whatever's supplied - normally, this just results in a sequence of scalars since the vector passed into for (as in your example above) is a row vector. This means that you can rewrite the above code like this:
function result = map_column(m, func)
result = [];
for m_col = m
result = horzcat(result, func(m_col));
end
If func does not return a column vector, then you can add something like
f = func(m_col);
result = horzcat(result, f(:));
to force it into a column.
Your solution is fine.
Note that horizcat exacts a substantial performance penalty for large matrices. It makes the code be O(N^2) instead of O(N). For a 100x10,000 matrix, your implementation takes 2.6s on my machine, the horizcat one takes 64.5s. For a 100x5000 matrix, the horizcat implementation takes 15.7s.
If you wanted, you could generalize your function a little and make it be able to iterate over the final dimension or even over arbitrary dimensions (not just columns).
Maybe you could always transform the matrix with the ' operator and then transform the result back.
smoothed = smooth(input', 9)';
That at least works with the fft function.
A way to cause an implicit loop across the columns of a matrix is to use cellfun. That is, you must first convert the matrix to a cell array, each cell will hold one column. Then call cellfun. For example:
A = randn(10,5);
See that here I've computed the standard deviation for each column.
cellfun(#std,mat2cell(A,size(A,1),ones(1,size(A,2))))
ans =
0.78681 1.1473 0.89789 0.66635 1.3482
Of course, many functions in MATLAB are already set up to work on rows or columns of an array as the user indicates. This is true of std of course, but this is a convenient way to test that cellfun worked successfully.
std(A,[],1)
ans =
0.78681 1.1473 0.89789 0.66635 1.3482
Don't forget to preallocate the result matrix if you are dealing with large matrices. Otherwise your CPU will spend lots of cycles repeatedly re-allocating the matrix every time it adds a new row/column.
If this is a common use-case for your function, it would perhaps be a good idea to make the function iterate through the columns automatically if the input is not a vector.
This doesn't exactly solve your problem but it would simplify the functions' usage. In that case, the output should be a matrix, too.
You can also transform the matrix to one long column by using m(:,:) = m(:). However, it depends on your function if this would make sense.