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 :)
Related
I want to make an iteration where I change a matrix's elements using pointwise multiplication, but use conditionals to only change some elements. However, using conditionals with matrices only seems to let you assign a scalar to some elements, not a full matrix.
I tried using conditionals to determine which elements are iterated, but using conditionals changes the dimensions of the matrix to a one dimensional array.
y=-1:0.005:1;
[X,Y]=meshgrid(x,y);
Z=X+1i*Y;
Zn=0*Z;
Iter=0*Z;
for m=1:1000
Zn = Zn.^2+Z;
Iter(Iter==0 & (abs(Zn)>10))=m;
endfor
p=pcolor(X,Y,Iter);
set(p,'edgecolor','none')
axis equal
Here's my full program. It iterates over a matrix to do the Mandelbrot graph. It works fine, but the online lessons I'm doing ( https://ocw.mit.edu/courses/mathematics/18-s997-introduction-to-matlab-programming-fall-2011/fractals-and-chaos/truth-statements-and-logical-indexing/ ) want you to stop the iterations for elements already larger than 10, to make it more efficient.
Inside the for loop you see the Iter matrix, this does exactly what I want it to. Since I'm assigning a scalar to certain elements using conditionals works just fine. Above it though is my matrix that I'm iterating, Zn. I'd like to write something like Zn(Zn<10) = Zn.^2+Z; but this gives me the error:
error: mandel: =: nonconformant arguments (op1 is 154633x1, op2 is 401x401)
error: called from
mandel at line 9 column 13
Conditionals turn a matrix into a one dimensional array, so this doesn't work. So my questions are
Why would they turn it into a one dimensional array? This is horribly unhelpful when manipulating matrices.
How can I get around this and only iterate certain elements, to make my code more efficient?
Edit: I'm suing Octave 5.1.0 on Windows.
I'm trying to finish a program and for some reason, the matrix I loaded into Matlab is messing with the ability to select the rows inside it. I'm trying to select all the rows in the matrix and see which values match the criteria for a Live setting. However I can select specific values/sections of the matrix in the command window without issue. Why is this happening? Any ideas?
It appears to only happen when in a for loop, I can do it just fine when it's on its own.
The syntax is: for x = start:stop. I think you are trying to do a for to the whole "A" matrix. You can split "A", according to its format (e.g. if is a table split in two variables).
bye
Richardd is right on; you're trying to iterate on a matrix, no good.
If I read you right, you're trying to run through your A matrix one column at a time, and see all the rows in that column? Assuming that is correct...
Your A matrix is 14x3, so you should go through your for loop 3 times, which is the size of your column dimension. Luckily, there is a function that MATLAB gives you to do just that. Try:
for iColumn = 1:size(A,2)
...
end
The size function returns the size of your array in a vector of [rows, columns, depth...] - it will go as many dimensions as your array. Calling size(A,2) returns only the size of your array in the column dimension. Now the for loop is iterating on columns.
I have a function that takes upto seven arguments and returns a row vector. The first three arguments are vectors (column, column, row) and the remaining four are optional scalars.
I want to use bsxfun() to apply the function to a vector of its last argument. Below is my attempt to do that.
o = #(m,pulse,N0,samples_per_pulse,sample_select,filter,channel_cutoff) ELE452Functions.EvaluateBER(m,pulse,N0,samples_per_pulse,sample_select,filter,channel_cutoff);
oo = #(m,pulse,N0,samples_per_pulse,sample_select,filter,channel_cutoff) bsxfun(#(N0,channel_cutoff) o(m,pulse,N0,samples_per_pulse,sample_select,filter,channel_cutoff), N0' , channel_cutoff);
when I try to call the function with a vector, oo(m,pulse,N0,1,1,1,[0.5 0.2]); for example, I get this error:
Error using bsxfun
Invalid output dimensions.
I am not experienced in using bsxfun and I tried to follow the documentation.
Update:
May be this is a clearer way to ask my question:
I want to use bsxfun to rewrite (improve) the code below with out a loop.
for i=1:length(channel_normalized_cuttoffs)
BER_LPchannel(i,:) = ELE452Functions.EvaluateBER(m,pulse,N0,1,1,1,channel_normalized_cuttoffs(i));
end
The idea behind bsxfun is to evaluate a certain function for all possible combinations of two elements (b in bsxfun stands for binary), each coming from one of the arrays. (NB: This is valid if you use it with a row and a column vector. But bsxfun can also do more.)
What you want to achieve is simply: For all entries of a single array, evaluate a function.
So bsxfun is just not the correct choice here.
You could use arrayfun instead, but this still may not perform a lot better than your original for loop, as it looks like the Matlab JIT Compiler would be able to optimize most of it, considering it's simplicity.
As I don't have the code of your function, I'm not able to test it, but your solution might look a lot like this:
evalBER = #(CNcutoffi) ELE452Functions.EvaluateBER(m,pulse,N0,1,1,1,CNcutoffi);
BER_LPchannel = arrayfun(evalBER, channel_normalized_cuttoffs, 'UniformOutput', false)
I am trying to use MATLAB in order to generate a variable whose elements are either 0 or 1. I want to define this variable using some kind of concatenation (equivalent of Java string append) so that I can add as many 0's and 1's according to some upper limit.
I can only think of using a for loop to append values to an existing variable. Something like
variable=1;
for i=1:N
if ( i%2==0)
variable = variable.append('0')
else
variable = variable.append('1')
i=i+1;
end
Is there a better way to do this?
In MATLAB, you can almost always avoid a loop by treating arrays in a vectorized way.
The result of pseudo-code you provided can be obtained in a single line as:
variable = mod((1:N),2);
The above line generates a row vector [1,2,...,N] (with the code (1:N), use (1:N)' if you need a column vector) and the mod function (as most MATLAB functions) is applied to each element when it receives an array.
That's not valid Matlab code:
The % indicates the start of a comment, hence introducing a syntax error.
There is no append method (at least not for arrays).
Theres no need to increment the index in a for loop.
Aside of that it's a bad idea to have Matlab "grow" variables, as memory needs to be reallocated at each time, slowing it down considerably. The correct approach is:
variable=zeros(N,1);
for i=1:N
variable(i)=mod(i,2);
end
If you really do want to grow variables (some times it is inevitable) you can use this:
variable=[variable;1];
Use ; for appending rows, use , for appending columns (does the same as vertcat and horzcat). Use cat if you have more than 2 dimensions in your array.
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.