What's the most idiomatic way to create a vector with a 1 at index i? - matlab

In Matlab, suppose I would like to create a 0-vector of length L, except with a 1 at index i?
For example, something like:
>> mostlyzeros(6, 3)
ans =
0 0 1 0 0 0
The purpose is so I can use it as a 'selection' vector which I'll multiply element-wise with another vector.

The simplest way I can think of is this:
a = (1:N)==m;
where N>=m. Having said that, if you want to use the resulting vector as a "selection vector", I don't know why you'd multiply two vectors elementwise, as I would expect that to be relatively slow and inefficient. If you want to get a vector containing only the m-th value of vector v in the m-th position, this would be a more straightforward method:
b = ((1:N)==m)*v(m);
Although the most natural method would have to be this:
b(N)=0;
b(m)=v(m);
assuming that b isn't defined before this (if b is defined, you need to use zeros rather than just assigning the Nth value as zero - it has been my experience that creating a zero vector or matrix that didn't exist before that is most easily done by assigning the last element of it to be zero - it's also useful for extending a matrix or vector).

I'm having a hard time thinking of anything more sensible than:
Vec = zeros(1, L);
Vec(i) = 1;
But I'd be happy to be proven wrong!
UPDATE: The one-liner solution provided by #GlenO is very neat! However, be aware that if efficiency is the chief criteria, then a few speed tests on my machine indicate that the simple method proposed in this answer and the other two answers is 3 or 4 times faster...
NEXT UPDATE: Ah! So that's what you mean by "selection vectors". #GlenO has given a good explanation of why for this operation a vector of ones and zeros is not idiomatic Matlab - however you choose to build it.
ps Try to avoid using i as a subscript, since it is actually a matlab function.

Just for the fun of it, another one-liner:
function [out] = mostlyzeros(idx, L)
out([L, idx]) = [0 1];

I can think of:
function mostlyones(m,n)
mat=zeros(1,m);
mat(n)=1;
Also, one thing to note. In MATLAB, index starts from one and not from zero. So your function call should have been mostlyzeros(6,3)

I would simply create a zero-vector and change whatever value you like to one:
function zeroWithOne(int numOfZeros, int pos)
a = zeros(numOfZeros,1);
a(pos) = 1;

Another one line option, which should be fast is:
vec = sparse(1, ii, 1, 1, L);

Related

Subtract all elements in an array from each other consecutively

As the question says:
x = [1 2 3]
1 - 2 - 3 = -4
How do I get my -4?
Without a for-loop.
diff doesn't work. I don't get how Matlab has a way to SUM, but not a way to subtract.
It's an odd operation, I doubt there's a builtin function for that, but an easy way to do it would be:
2*x(1)-sum(x)
Another alternative is using dot product:
y = x*[1 ; -ones(numel(x)-1, 1)];
Here x is assumed a row vector.
Though probably not the best solution in your case, it can be nice say if you want other pattern for the summation, e.g. with weights - just replace the vector to the right by a vector of weights.

Mathematica Table function to Matlab

I need to convert this to Matlab code, and am struggling without the "table" function.
Table[{i,1000,ability,savingsrate,0,RandomInteger[{15,30}],1,0},{i,nrhhs}];
So basically, these values are all just numbers, and I think I need to use a function handle, or maybe a for loop. I'm no expert, so I really need some help?
I'm not an expert in Mathematics (just used it long time ago). According to this documentation for Table function, you are using this form:
Table[expr, {i, imax}]
generates a list of the values of expr when i runs from 1 to imax.
It looks like your statement will produce list duplicating the list in first argument increasing i from 1 to nrhhs and using different random number.
In MATLAB the output can be equivalent to a matrix or a cell array.
To create a matrix with rows as your lists you can do:
result = [ (1:nrhhs)', repmat([1000,ability,savingsrate,0],nrhhs,1), ...
randi([15 30],nrhhs,1), repmat([1,0],nrhhs,1) ];
You can convert the above matrix to a cell array:
resultcell = cell2mat(result, ones(nrhhs,1));
The "Table" example you gave creates a list of nrhhs sub-lists, each of which contains 8 numbers (i, 1000, ability, savingsrate, 0, a random integer between 15 and 30 inclusive, 1, and 0). This is essentially (though not exactly) the same as an nrhhs x 8 matrix.
Assuming you do just want a matrix out, though, an analogous for loop in Matlab would be:
result = zeros(nrhhs,8); % preallocate memory for the result
for i = 1:nrhhs
result(i,:) = [i 1000 ability savingsrate 0 randi([15 30]) 1 0];
end
This method is likely slower than yuk's answer (which makes much more efficient use of vectors to avoid the for loop), but might be a little easier to pick apart depending on how familiar you are with Matlab.

Binary operation with singleton expansion -- scalar output

There is such function as bsxfun: http://www.mathworks.com/help/techdoc/ref/bsxfun.html however it work in element-by-element mode. I want similar function which works in vector-by-vector mode (and with scalar output).
As illustration I would try to use here bsxfun in such way. As inner function I will use (this is just an example) dot product of vectors.
function f = foo(a,b), f=a'*b; printf("called\n");, end
The above dummy function foo expects 2 vector, the result is scalar. Each time it is called we will see a message.
bsxfun(#foo,[2;3],[1 5;4 3])
The result is:
called
called
ans =
14 19
0 0
So, two calls (nice), however instead of a vectors (pair of 2 scalars) we got a matrix. One can say, it will suffice to get just first row in such case, because the matrix is the created in advance by bsxfun, and the rest will be always zeros.
But it is not always a case -- sometimes I got some real values, not only zeros -- and I am afraid some side-effects are involved (the above dot product is the simplest example which came to head).
Question
So, is there a function similar to bsxfun, but which gets vectors and expects a scalar, per each operation of those vectors?
I don't think there is a built in function, but using arrayfun or cellfun you might be able to do something. Generally arrayfun is also element-wise, but if you first split your larger array into a cell then you can do it:
foo = #(a,b) b*a
y = [2;3];
X = [1 5; 4 3];
% split X into cell array of rows
% apply foo to each row
cellfun(#(x) foo(y,x), num2cell(X,2))
ans =
17
17
I am not sure it would give any speed advantage (I would imagine an explicit loop would be quicker) but sometimes it can be easier to read.

How can I test submatrices of a matrix to see if they contain all zeroes?

I've a large matrix, say A[1,10,10000], which contains 10000 1-by-10 submatrices. I want to check each of these submatrices to find which ones contain all zeroes. How can I do this?
You could do this using the functions ALL and SQUEEZE:
allZeroIndex = squeeze(all(all(A == 0,2),1));
And this will give you a logical vector allZeroIndex that has the same length as the third dimension of A and contains a 1 (i.e. true) for matrices that have all zeroes and 0 (i.e. false) for matrices that contain non-zero values.
NOTE: Of course the above would really only be appropriate for a matrix of integer values. If there is the chance that you will have floating point values in A, then odds are good that you may never get exactly 0 for a value. In such a case, you need to check for values that are within some threshold of 0, like so:
allNearZeroIndex = squeeze(all(all(abs(A) < 1e-10,2),1));
The simple answer is to use nnz.
if nnz(A) == 0
disp('Yup, this is one really boring matrix.')
end
Instead of all, you can also use sum:
allZero = sum(sum(A==0)); % will be non-zero if there are non-zero values
I think using nnz is probably the best bet, but didn't know about that until now. Instead I would have used unique(): if unique(A)==0 ...

Compact MATLAB matrix indexing notation

I've got an n-by-k sized matrix, containing k numbers per row. I want to use these k numbers as indexes into a k-dimensional matrix. Is there any compact way of doing so in MATLAB or must I use a for loop?
This is what I want to do (in MATLAB pseudo code), but in a more MATLAB-ish way:
for row=1:1:n
finalTable(row) = kDimensionalMatrix(indexmatrix(row, 1),...
indexmatrix(row, 2),...,indexmatrix(row, k))
end
If you want to avoid having to use a for loop, this is probably the cleanest way to do it:
indexCell = num2cell(indexmatrix, 1);
linearIndexMatrix = sub2ind(size(kDimensionalMatrix), indexCell{:});
finalTable = kDimensionalMatrix(linearIndexMatrix);
The first line puts each column of indexmatrix into separate cells of a cell array using num2cell. This allows us to pass all k columns as a comma-separated list into sub2ind, a function that converts subscripted indices (row, column, etc.) into linear indices (each matrix element is numbered from 1 to N, N being the total number of elements in the matrix). The last line uses these linear indices to replace your for loop. A good discussion about matrix indexing (subscript, linear, and logical) can be found here.
Some more food for thought...
The tendency to shy away from for loops in favor of vectorized solutions is something many MATLAB users (myself included) have become accustomed to. However, newer versions of MATLAB handle looping much more efficiently. As discussed in this answer to another SO question, using for loops can sometimes result in faster-running code than you would get with a vectorized solution.
I'm certainly NOT saying you shouldn't try to vectorize your code anymore, only that every problem is unique. Vectorizing will often be more efficient, but not always. For your problem, the execution speed of for loops versus vectorized code will probably depend on how big the values n and k are.
To treat the elements of the vector indexmatrix(row, :) as separate subscripts, you need the elements as a cell array. So, you could do something like this
subsCell = num2cell( indexmatrix( row, : ) );
finalTable( row ) = kDimensionalMatrix( subsCell{:} );
To expand subsCell as a comma-separated-list, unfortunately you do need the two separate lines. However, this code is independent of k.
Convert your sub-indices into linear indices in a hacky way
ksz = size(kDimensionalMatrix);
cksz = cumprod([ 1 ksz(1:end-1)] );
lidx = ( indexmatrix - 1 ) * cksz' + 1; #'
% lindx is now (n)x1 linear indices into kDimensionalMatrix, one index per row of indexmatrix
% access all n values:
selectedValues = kDimensionalMatrix( lindx );
Cheers!