Sampling from two vectors with randsample - matlab

I have 2 vectors (n and t) eg:
n t
1 5
5 3
5 2
2 6
2 9
Once I sample from vector n through randsample(n,1), I want to sample from the vector t but only from the values corresponding to that same one in vector n.
eg. If I drew a value of 2 from n, I then want to draw the value 6 or 9 from t. But how do I tell matlab to do that?

You could potentially do this:
out = t(n == randsample(n, 1))
This will create a filter based on whether n = its own random sample, ie if
randsample(n, 1) = 2
(n == randsample(n, 1)) = [0
0
0
1
1]
and applying this to t ie:
t(n == randsample(n, 1)) = [6
9]
which are the two corresponding values to 2 in n, but in t.
Hope this helps.
PS if you need just one value from t then you can randsample the output that this function gives you.

Simple one-liner, assuming you have them stored in a Nx2 matrix
nt = [
1 5;
5 3;
5 2;
2 6;
2 9];
meaning:
n = nt(:,1);
t = nt(:,2);
you can sample nSamples with replacement by randmonly indexing the matrix row-wise, i.e.:
nSamples = 5;
keepSamples = nt(randi(length(nt),nSamples,1),:);

Related

Equivalent Function in Matlab for Tuples for Mathematica?

Is there an equivalent function for tuples in Matlab as there is for Mathematica?
See the first example:
http://reference.wolfram.com/language/ref/Tuples.html
I just mean the outputs and not necessarily the braces.
Thank you.
As I stated in comments, you only need to adapt this answer. You can do it as follows:
function y = tuples(x, n)
y = cell(1,n);
[y{end:-1:1}] = ndgrid(x);
y = cat(n+1, y{:});
y = reshape(y, [], n);
This gives a matrix where each row is a tuple. For example:
>> tuples([1 2 5], 2)
ans =
1 1
1 2
1 5
2 1
2 2
2 5
5 1
5 2
5 5

Turning matrix diagonals to columns

I am looking for a matrix operation of the form: B = M*A*N where A is some general square matrix and M and N are the matrices I want to find.
Such that the columns of B are the diagonals of A. The first column the main diagonal, the second the diagonal shifted by 1 from the main and so on.
e.g. In MATLAB syntax:
A = [1, 2, 3
4, 5, 6
7, 8, 9]
and
B = [1, 2, 3
5, 6, 4
9, 7, 8]
Edit:
It seems a pure linear algebra solution doesn't exist. So I'll be more precise about what I was trying to do:
For some vector v of size 1 x m. Then define C = repmat(v,m,1). My matrix is A = C-C.';.
Therefore, A is essentially all differences of values in v but I'm only interested in the difference up to some distance between values.
Those are the diagonals of A; but m is so large that the construction of such m x m matrices causes out-of-memory issues.
I'm looking for a way to extract those diagonals in a way that is as efficient as possible (in MATLAB).
Thanks!
If you're not actually looking for a linear algebra solution, then I would argue that constructing three additional matrices the same size as A using two matrix multiplications is very inefficient in both time and space complexity. I'm not sure it's even possible to find a matrix solution, given my limited knowledge of linear algebra, but even if it is it's sure to be messy.
Since you say you only need the values along some diagonals, I'd construct only those diagonals using diag:
A = [1 2 3;
4 5 6;
7 8 9];
m = size(A, 1); % assume A is square
k = 1; % let's get the k'th diagonal
kdiag = [diag(A, k); diag(A, k-m)];
kdiag =
2
6
7
Diagonal 0 is the main diagonal, diagonal m-1 (for an mxm matrix) is the last. So if you wanted all of B you could easily loop:
B = zeros(size(A));
for k = 0:m-1
B(:,k+1) = [diag(A, k); diag(A, k-m)];
end
B =
1 2 3
5 6 4
9 7 8
From the comments:
For v some vector of size 1xm. Then B=repmat(v,m,1). My matrix is A=B-B.'; A is essentially all differences of values in v but I'm only interested in the difference up to some distance between values.
Let's say
m = 4;
v = [1 3 7 11];
If you construct the entire matrix,
B = repmat(v, m, 1);
A = B - B.';
A =
0 2 6 10
-2 0 4 8
-6 -4 0 4
-10 -8 -4 0
The main diagonal is zeros, so that's not very interesting. The next diagonal, which I'll call k = 1 is
[2 4 4 -10].'
You can construct this diagonal without constructing A or even B by shifting the elements of v:
k = 1;
diag1 = circshift(v, m-k, 2) - v;
diag1 =
2 4 4 -10
The main diagonal is given by k = 0, the last diagonal by k = m-1.
You can do this using the function toeplitz to create column indices for the reshuffling, then convert those to a linear index to use for reordering A, like so:
>> A = [1 2 3; 4 5 6; 7 8 9]
A =
1 2 3
4 5 6
7 8 9
>> n = size(A, 1);
>> index = repmat((1:n).', 1, n)+n*(toeplitz([1 n:-1:2], 1:n)-1);
>> B = zeros(n);
>> B(index) = A
B =
1 2 3
5 6 4
9 7 8
This will generalize to any size square matrix A.

MATLAB multidimensional array

I have been trying to use the multidimensional array function to store NxN vectors of length n in each (i,j) entry of a 3d matrix of NxNxn dimensions.
My code looks like:
a=zeros(N,N,n);
a(i,j,:)=v_ij; %here v is a vector of length n, which differs for each i,j
However when I try to extract each vector by typing e.g. a(1,1,:) I don't get a nice vector. Rather I get something like:
ans(:,:,1) = ..
ans(:,:,2) = ..
...
I don't understand why it says ans(:,:)...
That's because each vector v_ij is stored along the 3rd dimension of your matrix, so when you access a(1,1,:), you are looking for a multidimensional array consisting of every value at the location (1,1) along the 3rd dimension of a.
Let's consider a simple example:
N = 2;
n = 3;
a = zeros(N,N,n);
for k = 1:N
for l = 1:N
v_kl = randi([0 10],1,n);
a(k,l,:) = v_kl;
end
end
The randomly-generated matrix a is a 2x2x3 matrix that looks like this:
a(:,:,1) =
4 1
4 10
a(:,:,2) =
0 2
0 5
a(:,:,3) =
2 2
9 5
Therefore, using a(1,1,:) is equivalent to getting the element located at (1,1) for all 3 dimensions, here it would be 4,0 and 2.
Indeed, calling a(1,1,:) yields:
ans(:,:,1) =
4
ans(:,:,2) =
0
ans(:,:,3) =
2
Benoit_11's answer plus squeeze should work, but I would like to propose a different solution.
Rather than creating a NxNxn array, why not make it nxNxN?
N = 2;
n = 3;
a = zeros(n,N,N);
for p = 1:N
for q = 1:N
v_pq = randi([0 10],1,n);
a(:,p,q) = v_pq;
if (p == 1) && (q == 1)
v_pq %// display vector at a(:,1,1)
end
end
end
a
v_pq =
3 4 8
a =
ans(:,:,1) =
3 3
4 9
8 7
ans(:,:,2) =
5 6
10 1
9 5
Now the vectors are stored along the first dimension, so [3 4 8] shows up as the first column of ans(:,:,1). To access it you would use a(:,p,q) rather than a(p,q,:):
a(:,1,1)
ans =
3
4
8

Rotate the rows of a matrix (like GAUSS function rotater)

I'm currently bringing some GAUSS code over to Matlab and I'm stuck trying to use the GAUSS "rotater" function.
The command reference entry for rotater says:
Purpose Rotates the rows of a matrix
Format y = rotater(x,r)
Input x: N x K matrix to be rotated. r: N x 1 or 1 x 1 matrix specifying the amount of rotation.
Output y: N x K rotated matrix.
Remarks The rotation is performed horizontally within each row of the matrix. A positive rotation value will cause the elements to move
to the right. A negative rotation will cause the elements to move to
the left. In either case, the elements that are pushed off the end of
the row will wrap around to the opposite end of the same row. If the rotation value is greater than or equal to the number of columns in x, then the rotation value will be calculated using (r % cols(x)).
Example 1
(I'm following Matlab's notation here, with straight brackets for matrices and a semicolon for a new ro)
If x = [1 2 3; 4 5 6], and r = [1; -1],then y = [3 1 2; 5 6 4]
Example 1
If x = [1 2 3; 4 5 6; 7 8 9; 10, 11, 12], and r = [0; 1; 2; 3], then y = [1 2 3; 6 4 5; 8 9 7; 10 11 12]
Maybe someone has found a function like that somewhere or can give me advice how to write it?
This can be done using bsxfun twice:
Compute rotated row indices by subtracting r with bsxfun and using mod. As usual, mod needs indices starting at 0, not 1. The rotated row indices are left as 0-based, because that's more convenient for step 2.
Get a linear index from columns and rotated rows, again using bsxfun. This linear index applied to x gives y:
Code:
[s1 s2] = size(x);
rows = mod(bsxfun(#plus, 1:s2, -r(:))-1, s2); % // step 1
y = x(bsxfun(#plus, rows*s1, (1:s1).')); %'// step 2
circshift is pretty close to what you're looking for except that 1) it works on columns rather than rows, and 2) it shifts the entire matrix by the same offset.
The first one is easy to fix, we just transpose. For the second one I haven't been able to find a vectorized approach, but in the meantime, here's a version with a for loop:
x = [1 2 3; 4 5 6; 7 8 9; 10 11 12]
r = [0 1 2 3]
B = x'
C = zeros(size(B));
for ii = 1:size(B,2)
C(:,ii) = circshift(B(:,ii),r(ii));
end
y = C'
The output is:
x =
1 2 3
4 5 6
7 8 9
10 11 12
r =
0 1 2 3
B =
1 4 7 10
2 5 8 11
3 6 9 12
y =
1 2 3
6 4 5
8 9 7
10 11 12
This can be done using a simple for loop to iterate over each row, and a function called 'circshift' from matlab.
I created a function the goes through each row and applies the appropriate shift to it. There may be more efficient ways to implement this, but this way works with your examples. I created a function
function rotated_arr = GaussRotate(input_array, rotation_vector)
[N,K] = size(input_array)
%creates array for return values
rotated_arr = zeros(N,K);
%if the rotation vector is a scalar
if (length(rotation_vector) == 1)
%replicate the value once for each row
rotation_vector = repmat(rotation_vector, [1,N]);
end
%if the rotation vector doesn't have as many entries as there are rows
%in the input array
if (length(rotation_vector) ~= N)
disp('ERROR GaussRotate: rotation_vector is the wrong size')
disp('if input_Array is NxK, rotation_vector must be Nx1 or 1x1')
return
end
%for each row
for idx=1:size(input_array,1)
%shift the row by the appropriate number of columns
%we use [0,shift] because we want to shift the columns, the row
%stays where it is (even though this is a 1xN at this point we
%still specify rows vs columns)
rotated_arr(idx,:) = circshift(input_array(idx,:),[0,rotation_vector(idx)]);
end
end
then simply called it with your examples
x = [1 2 3; 4 5 6];
r = [1; -1];
y = GaussRotate(x,r)
%produces [3 1 2; 5 6 4]
%I also made it support the 1x1 case
r = [-1]
%this will shift all elements one column to the left
y = GaussRotate(x,r)
%produces [2 3 1; 5 6 4]
x = [1 2 3; 4 5 6; 7 8 9; 10, 11, 12]
r = [0; 1; 2; 3]
y = GaussRotate(x,r)
%produces [1 2 3; 6 4 5; 8 9 7; 10 11 12]

Set column to 0 with probability p

I've got a matrix A with the dimensions m X n. For every column i (i > 0and i <= n) I want to flip a coin and fill the whole column with 0 values with probability p. How can this be accomplished in MATLAB?
Example:
A = [1 2 3 4; 5 6 7 8] and p = 0.5 could result in
A' = [1 0 3 0; 5 0 7 0]
You can use the function rand() to generate an array of uniformly distributed random numbers, and use logical indexing to select colums where that array is less than p:
A = [1 2 3 4; 5 6 7 8];
p = 0.5;
A(:, rand(size(A,2), 1)<p) = 0
A =
0 2 0 0
0 6 0 0
You can do something like bsxfun(#times, A, rand(1, size(A, 2)) > p). Alex's answer is admittedly better, though.