I have a large dataset that I need to divide randomly into 5 almost equal sized sets for cross validation. I have happily used _crossvalind_ to divide into sets before, however this time I need to divide chunks of data into these groups at a time.
Let's say my data looks like this:
data = [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18];
Then I want to divide them randomly into 5 groups in chunks of 2, e.g. like this
g1 = [3 4], [11 12]
g2 = [9 10]
g3 = [1 2], [15 16]
g4 = [7 8], [17 18]
g5 = [5 6], [13 14]
I think I can do this with some for-loops, but I'm guessing there must be a much more cost-efficient way to do it in matlab :-)
Any suggestions?
I'm interpreting your needs to be random ordering of sets, but within each set, the ordering of elements is unchanged from the parent set. You can use randperm to randomly order the number of sets and use linear indexing for the elements.
dataElements=numel(data);%# get number of elements
totalGroups=5;
groupSize=dataElements/totalGroups;%# I'm assuming here that it's neatly divisible as in your example
randOrder=randperm(totalGroups);%# randomly order of numbers from 1 till totalGroups
g=reshape(data,groupSize,totalGroups)'; %'# SO formatting
g=g(randOrder,:);
The different rows of g give you the different groupings.
You can shuffle the array (randperm) and then divide it into consequentive equal parts.
data = [10 20 30 40 50 60 70 80 90 100 110 120 130 140 150];
permuted = data(randperm(length(data)));
% padding may be required if the length of data is not divisible by the size of chunks
k = 5;
g = reshape(permuted, k, length(data)/k);
Related
I'm stuck on this probably very trivial problem.
I have a matrix like this (just much larger):
A = [1 3 4 8 10 12 14 17 19; 5 30 90 30 50 70 5 30 5]'
I'm now looking for pairs of specific numbers in A(:, 2). For example, I'd like to find all 30s that are preceded by 5s in A(:, 2) and extract the corresponding row in A(:, 1).
So I'd like to end up, in this example, with B = [3, 17];
How can I do that in Matlab? Any help much appreciated.
You can run:
num_wanted=30;
num_previous=5;
is_match=[ false; A(1:end-1,2)==num_previous & A(2:end,2)==num_wanted ]; %the first element cannot be a match
A(is_match,1).',
I want to repeat a row vector to create a matrix, in which every row is a slightly modified version of the original vector.
For example, if I have a vector v = [10 20 30 40 50], I want every row of my matrix to be that vector, but with a random number added to every element of the vector to add some fluctuations.
My matrix should look like this:
M = [10+a 20+a 30+a 40+a 50+a;
10+b 20+b 30+b 40+b 50+b;
... ]
Where a, b, ... are random numbers between 0 and 2, for an arbitrary number of matrix rows.
Any ideas?
In Matlab, you can add a column vector to a matrix. This will add the vector elements to each of the row values accordingly.
Example:
>> M = [1 2 3; 4 5 6; 7 8 9];
>> v = [1; 2; 3];
>> v + M
ans =
2 3 4
6 7 8
10 11 12
Note that in your case v is a row vector, so you should transpose it first (using v.').
As Sardar Usama and Wolfie note, this method of adding is only possible since MATLAB version R2016b, for earlier versions you will need to use bsxfun:
>> % instead of `v + M`
>> bsxfun(#plus, v, M)
ans =
2 4 6
5 7 9
8 10 12
If you have a MATLAB version earlier than 2016b (when implicit expansion was introduced, as demonstrated in Daan's answer) then you should use bsxfun.
v = [10 20 30 40 50]; % initial row vector
offsets = rand(3,1); % random values, add one per row (this should be a column vector)
output = bsxfun(#plus,offsets,v);
Result:
>> output =
10.643 20.643 30.643 40.643 50.643
10.704 20.704 30.704 40.704 50.704
10.393 20.393 30.393 40.393 50.393
This can be more easily understood with less random inputs!
v = [10 20 30 40 50];
offsets = [1; 2; 3];
output = bsxfun(#plus,offsets,v);
>> output =
11 21 31 41 51
12 22 32 42 52
13 23 33 43 53
Side note: to get an nx1 vector of random numbers between 0 and 2, use
offsets = rand(n,1)*2
I have two arrays threshold and values.
threshold=[10 22 97]
values=[99 23 77 11 8 10]
I want to output idx such that threshold(idx-1)<values(i)<=threshold(idx). That is for the above example output will be
output=[4 3 3 2 1 1]
The naive code that can produce above output will be
output=ones(1,length(values))*(length(values)+1);
for i=1:length(values)
for j=1:length(threshold)
if(values(i)>threshold(j))
output(i)=j;
end
end
end
Is there a simple way of doing it. I want to avoid loops.
You can use histc command, with a slight adjustment of threshold array
>> threshold=[-inf 10 22 97 inf];
>> values=[99 23 77 11 8 10];
>> [~, output] = histc( values, threshold+.1 )
output =
4 3 3 2 1 1
The modification of threshold is due to "less-than"/"less-than-equal" type of comparison for bin boundary decisions.
No loops often means you'll gain speed by increasing peak memory. Try this:
threshold = [10 22 97];
values = [99 23 77 11 8 10];
%// Do ALL comparisons
A = sum(bsxfun(#gt, values.', threshold));
%// Find the indices and the ones before
R = max(1, [A; A-1]);
%// The array you want
R(:).'
If you run out of memory, just use the loop, but then with a find replacing the inner loop.
Loops aren't all that bad, you know (if you have MATLAB > R2008). In theory, the solution above shouldn't even be faster than a loop with find, but oh well...profiling is key :)
I have a matrix of 2d lets assume the values of the matrix
a =
17 24 1 8 15
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
17 24 1 8 15
11 18 25 2 9
This matrix is going to be divided into three different matrices randomly let say
b =
17 24 1 8 15
23 5 7 14 16
c =
4 6 13 20 22
11 18 25 2 9
d =
10 12 19 21 3
17 24 1 8 15
How can i know the index of the vectors in matrix d for example in the original matrix a,note that the values of the matrix can be duplicated.
for example if i want to know the index of {10 12 19 21 3} in matrix a?
or the index of {17 24 1 8 15} in matrix a,but for this one should return only on index value?
I would appreciate it so much if you can help me with this. Thank you in advance
You can use ismember with the 'rows' option. For example:
tf = ismember(a, c, 'rows')
Should produce:
tf =
0
0
1
0
0
1
To get the indices of the rows, you can apply find on the result of ismember (note that it's redundant if you're planning to use this vector for matrix indexing). Here find(tf) return the vector [3; 6].
If you want to know the number of the row in matrix a that matches a single vector, you either use the method explained and apply find, or use the second output parameter of ismember. For example:
[tf, loc] = ismember(a, [10 12 19 21 3], 'rows')
returns loc = 4 for your example. Note that here a is the second parameter, so that the output variable loc would hold a meaningful result.
Handling floating-point numbers
If your data contains floating point numbers, The ismember approach is going to fail because floating-point comparisons are inaccurate. Here's a shorter variant of Amro's solution:
x = reshape(c', size(c, 2), 1, []);
tf = any(all(abs(bsxfun(#minus, a', x)) < eps), 3)';
Essentially this is a one-liner, but I've split it into two commands for clarity:
x is the target rows to be searched, concatenated along the third dimension.
bsxfun subtracts each row in turn from all rows of a, and the magnitude of the result is compared to some small threshold value (e.g eps). If all elements in a row fall below it, mark this row as "1".
It depends on how you build those divided matrices. For example:
a = magic(5);
d = a([2 1 2 3],:);
then the matching rows are obviously: 2 1 2 3
EDIT:
Let me expand on the idea of using ismember shown by #EitanT to handle floating-point comparisons:
tf = any(cell2mat(arrayfun(#(i) all(abs(bsxfun(#minus, a, d(i,:)))<1e-9,2), ...
1:size(d,1), 'UniformOutput',false)), 2)
not pretty but works :) This would be necessary for comparisons such as: 0.1*3 == 0.3
(basically it compares each row of d against all rows of a using an absolute difference)
I have an m x n matrix and I want to use it in some neural networks applications in MATLAB.
For example,
A = [ 24 22 35 40 30 ; 32 42 47 45 39 ; 14 1 10 5 9 ; 2 8 4 1 8] ;
I want to randomly train some columns and test the other remaining columns.
So, the first matrix will contain three random, distinct columns taken from the original matrix A, while the second matrix contains the remaining two columns.
How can I extract these matrices ?
This will do:
s = randperm(5);
train = A(:, s(1:3));
test = A(:, s(4:end));
Neural Network Toolbox comes with a set of functions that do this for you, such as dividerand and divideblock.