Sorting Data, Getting Rid of Rows - matrix

Hi I'm trying to sort data by creating a new matrix from my current matrix data, that leaves out rows when a condition are met. For example, if I only want to keep the rows that have column 17's value as < 2, then I wrote:
B=[0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0];
count=0
for n = 1:19709
if abs(G(n,17)) < 2
B(n,:)=G(n,:)
end
count=count+1
if count>19709
break
end
end
But this code instead returns a row of zeros when the conditions are not met, rather than just leaving out the row, but I'm not sure whats wrong with the code. Thank you!

Related

Fill an n*n array with 1s and 0s

So Im trying to fill in array with 1s and 0s given the number of elements in each row and column.
for example if i have been given
int Row = {2, 2, 2, 3};
int Column = { 3, 2, 1, 3};
then a possible solution is
1 0 0 1
1 1 0 0
0 0 1 1
1 1 0 1
secondly is there any combination in which a valid solution is not possible even if the sum of both arrays (column and row) are equal. In my case it should be valid because 3+2+1+3=2+2+2+3 but is there any case in which both the sums are equal but there still doesn't exist a stable combination.
The answer i found was a greedy approach in which answer each subproblem. So i go column by column and fill in each column depending on the weight of the row.
Remember indexing start with 0
I start with column 0
since row 3 has the highest value (3) i fill it
0 0 0 0
0 0 0 0
0 0 0 0
1 0 0 0
now the row and column array are as follows
row = {2,2,2,2}
column = {2,2,1,3}
i keep filling until i can no longer insert more i.e column[0]=0
1 0 0 0
0 0 0 0
0 0 0 0
1 0 0 0
row = {1,2,2,2}
column={2,2,1,2}
1 0 0 0
1 0 0 0
0 0 0 0
1 0 0 0
row = {1,1,2,2}
column={2,1,1,2}
now since column[0]==0 i can go to the next column and perform the same procedure again

Sorting rows and columns of adjacency matrix to reveal cliques

I'm looking for a reordering technique to group connected components of an adjacency matrix together.
For example, I've made an illustration with two groups, blue and green. Initially the '1's entries are distributed across the rows and columns of the matrix. By reordering the rows and columns, all '1''s can be located in two contiguous sections of the matrix, revealing the blue and green components more clearly.
I can't remember what this reordering technique is called. I've searched for many combinations of adjacency matrix, clique, sorting, and reordering.
The closest hits I've found are
symrcm moves the elements closer to the diagonal, but does not make groups.
Is there a way to reorder the rows and columns of matrix to create a dense corner, in R? which focuses on removing completely empty rows and columns
Please either provide the common name for this technique so that I can google more effectively, or point me in the direction of a Matlab function.
I don't know whether there is a better alternative which should give you direct results, but here is one approach which may serve your purpose.
Your input:
>> A
A =
0 1 1 0 1
1 0 0 1 0
0 1 1 0 1
1 0 0 1 0
0 1 1 0 1
Method 1
Taking first row and first column as Column-Mask(maskCol) and
Row-Mask(maskRow) respectively.
Get the mask of which values contains ones in both first row, and first column
maskRow = A(:,1)==1;
maskCol = A(1,:)~=1;
Rearrange the Rows (according to the Row-mask)
out = [A(maskRow,:);A(~maskRow,:)];
Gives something like this:
out =
1 0 0 1 0
1 0 0 1 0
0 1 1 0 1
0 1 1 0 1
0 1 1 0 1
Rearrange columns (according to the column-mask)
out = [out(:,maskCol),out(:,~maskCol)]
Gives the desired results:
out =
1 1 0 0 0
1 1 0 0 0
0 0 1 1 1
0 0 1 1 1
0 0 1 1 1
Just a check whether the indices are where they are supposed to be or if you want the corresponding re-arranged indices ;)
Before Re-arranging:
idx = reshape(1:25,5,[])
idx =
1 6 11 16 21
2 7 12 17 22
3 8 13 18 23
4 9 14 19 24
5 10 15 20 25
After re-arranging (same process we did before)
outidx = [idx(maskRow,:);idx(~maskRow,:)];
outidx = [outidx(:,maskCol),outidx(:,~maskCol)]
Output:
outidx =
2 17 7 12 22
4 19 9 14 24
1 16 6 11 21
3 18 8 13 23
5 20 10 15 25
Method 2
For Generic case, if you don't know the matrix beforehand, here is the procedure to find the maskRow and maskCol
Logic used:
Take first row. Consider it as column mask (maskCol).
For 2nd row to last row, the following process are repeated.
Compare the current row with maskCol.
If any one value matches with the maskCol, then find the element
wise logical OR and update it as new maskCol
Repeat this process till the last row.
Same process for finding maskRow while the column are used for
iterations instead.
Code:
%// If you have a square matrix, you can combine both these loops into a single loop.
maskCol = A(1,:);
for ii = 2:size(A,1)
if sum(A(ii,:) & maskCol)>0
maskCol = maskCol | A(ii,:);
end
end
maskCol = ~maskCol;
maskRow = A(:,1);
for ii = 2:size(A,2)
if sum(A(:,ii) & maskRow)>0
maskRow = maskRow | A(:,ii);
end
end
Here is an example to try that:
%// Here I removed some 'ones' from first, last rows and columns.
%// Compare it with the original example.
A = [0 0 1 0 1
0 0 0 1 0
0 1 1 0 0
1 0 0 1 0
0 1 0 0 1];
Then, repeat the procedure you followed before:
out = [A(maskRow,:);A(~maskRow,:)]; %// same code used
out = [out(:,maskCol),out(:,~maskCol)]; %// same code used
Here is the result:
>> out
out =
0 1 0 0 0
1 1 0 0 0
0 0 0 1 1
0 0 1 1 0
0 0 1 0 1
Note: This approach may work for most of the cases but still may fail for some rare cases.
Here, is an example:
%// this works well.
A = [0 0 1 0 1 0
1 0 0 1 0 0
0 1 0 0 0 1
1 0 0 1 0 0
0 0 1 0 1 0
0 1 0 0 1 1];
%// This may not
%// Second col, last row changed to zero from one
A = [0 0 1 0 1 0
1 0 0 1 0 0
0 1 0 0 0 1
1 0 0 1 0 0
0 0 1 0 1 0
0 0 0 0 1 1];
Why does it fail?
As we loop through each row (to find the column mask), for eg, when we move to 3rd row, none of the cols match the first row (current maskCol). So the only information carried by 3rd row (2nd element) is lost.
This may be the rare case because some other row might still contain the same information. See the first example. There also none of the elements of third row matches with 1st row but since the last row has the same information (1 at the 2nd element), it gave correct results. Only in rare cases, similar to this might happen. Still it is good to know this disadvantage.
Method 3
This one is Brute-force Alternative. Could be applied if you think the previous case might fail. Here, we use while loop to run the previous code (finding row and col mask) number of times with updated maskCol, so that it finds the correct mask.
Procedure:
maskCol = A(1,:);
count = 1;
while(count<3)
for ii = 2:size(A,1)
if sum(A(ii,:) & maskCol)>0
maskCol = maskCol | A(ii,:);
end
end
count = count+1;
end
Previous example is taken (where the previous method fails) and is run with and without while-loop
Without Brute force:
>> out
out =
1 0 1 0 0 0
1 0 1 0 0 0
0 0 0 1 1 0
0 1 0 0 0 1
0 0 0 1 1 0
0 0 0 0 1 1
With Brute-Forcing while loop:
>> out
out =
1 1 0 0 0 0
1 1 0 0 0 0
0 0 0 1 1 0
0 0 1 0 0 1
0 0 0 1 1 0
0 0 0 0 1 1
The number of iterations required to get the correct results may vary. But it is safe to have a good number.
Good Luck!

Keep random values from matrix

I have a matrix, which contains N entries each with M rows. Each row contains of 0s and 1s. I want to create a second matrix with the same size, but in each row only one 1 should be left, every other value should be 0. Which value should be 1 should be chosen randomly.
E.g.:
0 1 1 0 1
1 1 0 0 1
0 0 1 1 0
->
0 1 0 0 0
1 0 0 0 0
0 0 0 1 0
Read the documentation of find and randperm
%//preallocate the output matrix
out = zeros(size(a));
%for each row, take a random sample from the indices holding value 1
for i = 1:size(a,1)
temp2 = find(a(i,:));
out(i,temp2(randperm(numel(temp2))(1))) = 1;
end
Watch the code in action here

Create a Matrix with conditions

I am struggling to create two matrix in SAS based on certain conditions.
trying to create a 12x12 matrix in the format below:
col1 col2 col3 col4 ............col12
1 0 0 0 ............ 0
1 1 0 0 ............ 0
1 1 1
0 1 1
0 0 1
1 0 0
1 1 0
1 1 1
0 1 1
0 0 1
0 0 0
0 0 0
and so on.
and this-
col1 col2 col3 col4 ............col12
1 0 0 0 ............ 0
1 2 0 0 ............ 0
1 2 3
0 2 3
0 0 3
1 0 0
1 2 0
1 2 3
0 2 3
0 0 3
0 0 0
0 0 0
and so on. Basically displays the col# instead of 1's.
I read a couple of articles online and tried Proc IML but i got an error that the procedure doesn't exist.
I tried the code below to start with but nothing. I am confused as to how should I enter the conditions.
data test_matrices ;
array col(12) col1-col12;
do i=1 to 12;
j=i-1;
col(i)=ifn(i le 5 , 1, 0,0);
output;
end;
run;
Please help.
Thanks.
Jay
What you need to start with:
Arrays have to have a name, and unless they're temporary arrays they also need variable names (they'll take the name concatenated with the array index if you don't provide it). So:
array (*) 1-12;
needs to be
array myVars(12) col1-col12;
You need two loops, one to define your 'rows' and one to work on your columns, nested. IE, for row 1, do something 12 times, for row 2, do something 12 times.
So this:
do i=1 to 12;
do j=1 to 12;
... do stuff ...
end;
output; *you had this right! It goes in the outer loop since it defines rows.;
end;
Now, you have something that lets you work on just one cell. So you're on cell (i,j); what rule defines what should go there? Figure out that logic, and then set myvars[j] to that value. You can't operate on the 'i' parameter, but instead that's going to just define how often you output.
Ie, this:
myvars[j] = i;
That's not correct, but figure out what is correct and assign that to myvars[j].

Counting subrows in each row of a matrix in Matlab?

I need an algorithm in Matlab which counts how many adjacent and non-overlapping (1,1) I have in each row of a matrix A mx(n*2) without using loops. E.g.
A=[1 1 1 0 1 1 0 0 0 1; 1 0 1 1 1 1 0 0 1 1] %m=2, n=5
Then I want
B=[2;3] %mx1
Specific case
Assuming A to have ones and zeros only, this could be one way -
B = sum(reshape(sum(reshape(A',2,[]))==2,size(A,2)/2,[]))
General case
If you are looking for a general approach that must work for all integers and a case where you can specify the pattern of numbers, you may use this -
patt = [0 1] %%// pattern to be found out
B = sum(reshape(ismember(reshape(A',2,[])',patt,'rows'),[],2))
Output
With patt = [1 1], B = [2 3]
With patt = [0 1], B = [1 0]
you can use transpose then reshape so each consecutive values will now be in a row, then compare the top and bottom row (boolean compare or compare the sum of each row to 2), then sum the result of the comparison and reshape the result to your liking.
in code, it would look like:
A=[1 1 1 0 1 1 0 0 0 1; 1 0 1 1 1 1 0 0 1 1] ;
m = size(A,1) ;
n = size(A,2)/2 ;
Atemp = reshape(A.' , 2 , [] , m ) ;
B = squeeze(sum(sum(Atemp)==2))
You could pack everything in one line of code if you want, but several lines is usually easier for comprehension. For clarity, the Atemp matrix looks like that:
Atemp(:,:,1) =
1 1 1 0 0
1 0 1 0 1
Atemp(:,:,2) =
1 1 1 0 1
0 1 1 0 1
You'll notice that each row of the original A matrix has been broken down in 2 rows element-wise. The second line will simply compare the sum of each row with 2, then sum the valid result of the comparisons.
The squeeze command is only to remove the singleton dimensions not necessary anymore.
you can use imresize , for example
imresize(A,[size(A,1),size(A,2)/2])>0.8
ans =
1 0 1 0 0
0 1 1 0 1
this places 1 where you have [1 1] pairs... then you can just use sum
For any pair type [x y] you can :
x=0; y=1;
R(size(A,1),size(A,2)/2)=0; % prealocarting memory
for n=1:size(A,1)
b=[A(n,1:2:end)' A(n,2:2:end)']
try
R(n,find(b(:,1)==x & b(:,2)==y))=1;
end
end
R =
0 0 0 0 1
0 0 0 0 0
With diff (to detect start and end of each run of ones) and accumarray (to group runs of the same row; each run contributes half its length rounded down):
B = diff([zeros(1,size(A,1)); A.'; zeros(1,size(A,1))]); %'// columnwise is easier
[is js] = find(B==1); %// rows and columns of starts of runs of ones
[ie je] = find(B==-1); %// rows and columns of ends of runs of ones
result = accumarray(js, floor((ie-is)/2)); %// sum values for each row of A

Resources