MATLAB: Conditionally matrix elements into two separate cell arrays - matlab

A matrix has 2 rows and several columns, and the first contains alternating strings of 1's and 0's. I want to use this binary as a decision to copy the information below it into one of two cell arrays. I understand that this can be done through iteration with the use of the IF conditional, or with while loops, but I'm having trouble cleaning it up.
For example, for
mat = [ 1 1 1 0 0 1 1 0 0 0 0 1 1 1 ;...
1 2 3 4 5 6 7 1 2 3 4 5 6 7 ]
I would like to output two cell arrays, one for the '1s', and one for the '0s':
1 2 3
6 7
5 6 7
and:
4 5
1 2 3 4

There are a couple of ways of doing this, I am sure. One might be using a loop; however, you can also make good use with the built-in find function. Below is a sample solution based on your example.
For '1s',
Here, we would like to get the indices with '1' from the first row.
on_array= mat(2, find(mat(1,:)));
or as suggested by #H.Muster
on_array= mat(2, mat(1,:)==1);
For '0s',
Here, we would like to get the indices with '0' from the first row.
off_array = mat(2, find(mat(1,:)==0));
or as suggested by #H.Muster
off_array= mat(2, mat(1,:)==0);
For the output format(the one that you want), i am sure you know what to do. Good luck.

Related

Finding the rows of a matrix with specified elements

I want to find the rows of a matrix which contain specified element of another matrix.
For example, a=[1 2 3 4 5 6 7] and b=[1 2 0 4;0 9 10 11;3 1 2 12]. Now, I want to find the rows of b which contain at least three element of a. For this purpose, I used bsxfun command as following:
c=find(sum(any(bsxfun(#eq, b, reshape(a,1,1,[])), 2), 3)>=3);
It works good for low dimension matrices but when I want to use this for high dimension matrices, for example, when the number of rows of b is 192799, MATLAB gives following error:
Requested 192799x4x48854 (35.1GB) array exceeds maximum array size preference.
Creation of arrays greater than this limit may take a long time and cause MATLAB
to become unresponsive. See array size limit or preference panel for more information.
Is there any other command which does this task without producing the behaviour like above for high dimension matrices?
a possible solution:
a=[1 2 3 4 5 6 7]
b=[1 2 0 4;0 9 10 11;3 1 2 12]
i=ismember(b,a)
idx = sum(i,2)
idx = find(idx>=3)

Accessing indexes as first columns of matrix in Matlab

I have data that is output from a computational chemistry program (Gaussian09) which contains sets of Force Constant data. The data is arranged with indexes as the first 2-4 columns (quadratic, cubic and quartic FC's are calculated). As an example the cubic FC's look something like this, and MatLab has read them in successfully so I have the correct matrix:
cube=[
1 1 1 5 5 5
1 1 2 6 6 6
.
.
4 1 1 8 8 8
4 2 1 9 9 9
4 3 1 7 7 7 ]
I need a way to access the last 3 columns when feeding in the indices of the first 3 columns. Something along the lines of
>>index=find([cube(:,1)==4 && cube(:,2)==3 && cube(:,3)==1]);
Which would give me the row number of the data that is index [ 4 3 1 ] and allow me to read out the values [7 7 7] which I need within loops to calculate anharmonic frequencies.
Is there a way to do this without a bunch of loops?
Thanks in advance,
Ben
You have already found one way to solve this, by using & in your expression (allowing you to make non-scalar comparisons).
Another way is to use ismember:
index = find(ismember(cube(:,1:3),[4 3 1]));
Note that in many cases, you may not even need the call to find: the binary vector returned by the comparisons or ismember can directly be used to index into another array.

Strange behaviour of MATLAB combnk function

I am trying to generate all combination of 2 elements in a given range of numbers. I am using 'combnk' function as follows.
combnk(1:4,2)
ans =
3 4
2 4
2 3
1 4
1 3
1 2
combnk(1:6,2)
ans =
1 2
1 3
1 4
1 5
1 6
2 3
2 4
2 5
2 6
3 4
3 5
3 6
4 5
4 6
5 6
The order of combinations returned appears to change. I need to know the order in advance for my program to work properly.
Is there any solution to make sure I get the combinations in a consistent order?
Also, why is MATLAB showing this strange behavior?
The only solution I can think of so far is to first check the 1st entry of the result matrix and flip it up side down using 'flipud' function.
Update: By a little bit of experimenting I noticed the reverse order occurs only when the length of the set of numbers is less than 6. This is why combnk(1:6,2) produce the 'correct' order. Where as combnk(1:5,2) produce the results backwards. This is still big problem.
You could try nchoosek instead of combnk. I don't have the matlab statistics toolbox (only octave), so I don't know if nchoosek has any significant disadvanvatages.
This will solve the ordering issue:
a=combnk(1:4,2);
[~,idx]=sortrows(a);
aNew=a(idx,:);
I don't know why MATLAB is showing this behavior.

Scramble an nx1 matrix in matlab efficiently?

I need to randomly scramble the values of an nx1 matrix in matlab. I'm not sure how to do this efficiently, I need to do it many times for n > 40,000.
Example
Matrix before:
1 2 2 2 3 4 5 5 4 3 2 1
Scrambled:
3 5 2 1 2 2 3 4 1 4 5 2
thank you
If your data is stored in matrix data, then you can generate "scrambled" data using randperm like so:
scrambled = data(randperm(numel(data)));
This is sampling without replacement, so every value in data will appear once in scrambled.
For sampling with replacement (values in data may appear in scrambled multiple times and some may not appear at all), you could use randi like this:
scrambled = data(randi(numel(data),1,numel(data)));

How can I sort a 2-D array in MATLAB with respect to one column?

I would like to sort a matrix according to a particular column. There is a sort function, but it sorts all columns independently.
For example, if my matrix data is:
1 3
5 7
-1 4
Then the desired output (sorting by the first column) would be:
-1 4
1 3
5 7
But the output of sort(data) is:
-1 3
1 4
5 7
How can I sort this matrix by the first column?
I think the sortrows function is what you're looking for.
>> sortrows(data,1)
ans =
-1 4
1 3
5 7
An alternative to sortrows(), which can be applied to broader scenarios.
save the sorting indices of the row/column you want to order by:
[~,idx]=sort(data(:,1));
reorder all the rows/columns according to the previous sorted indices
data=data(idx,:)