Deleting and retaining data in a cell array -Matlab - matlab

I have a set of data in a cell array ,a part of which is shown below.The first three columns of row 2 and row 3 are same.In the 2nd row from columns 4 onwards it contains P0702 which is already captured in row 3(with the same first three columns as row 2).So i would like the delete the 2nd row.Similarly 5 and 6th rows have same data in the first three columns.P0882 and P0702 in the fifth row is also present in the sixth row,so i would want to delete the 5th row .
Data before duplicates
'1FA' 2 'Fm' [] [] [] [] [] [] [] 'P2700' []
'1Fc' 2 'Fz' [] [] [] 'P0702' [] [] [] [] []
'1Fc' 2 'Fz' [] 'P0702' 'P0801' [] [] [] [] [] []
'1Fj' 8 'Fr' 'P0702' [] [] [] [] [] [] [] []
'1FAH' 2 'Fo' [] [] [] [] [] [] 'P0882' 'P0702' []
'1FAH' 2 'Fo' [] [] [] [] [] [] 'P0882' 'P0702' 'P2700'
Data after Duplicates
'1FA' 2 'Fm' [] [] [] [] [] [] [] 'P2700' []
'1Fc' 2 'Fz' [] 'P0702' 'P0801' [] [] [] [] [] []
'1Fj' 8 'Fr' 'P0702' [] [] [] [] [] [] [] []
'1FAH' 2 'Fo' [] [] [] [] [] [] 'P0882' 'P0702' 'P2700'
Any help would be great on this.

First reading the question I thought this should be possible in 2 or 3 lines, but it took some lines of code to solve:
M={'1FA' 2 'Fm' [] [] [] [] [] [] [] 'P2700' []
'1Fc' 2 'Fz' [] [] [] 'P0702' [] [] [] [] []
'1Fc' 2 'Fz' [] 'P0702' 'P0801' [] [] [] [] [] []
'1Fj' 8 'Fr' 'P0702' [] [] [] [] [] [] [] []
'1FAH' 2 'Fo' [] [] [] [] [] [] 'P0882' 'P0702' []
'1FAH' 2 'Fo' [] [] [] [] [] [] 'P0882' 'P0702' 'P2700' }
%r contains the number of nonempty cells, you want those with highest r
r=sum(cellfun(#(x)~isempty(x),(M(:,4:end))),2);
%Create a index matrix which maps each string of first and third column to
%a double, which allows to use unique.
[~,~,index]=unique(M(:,1));
index(:,2)=[M{:,2}];
[~,~,index(:,3)]=unique(M(:,3));
%fill fourth colum with consecutive numbers, used to restore original
%ordering
index(:,4)=1:size(index,1);
%Next two lines, sort index to have rows with highetst r first
[~,sorted_most_content]=sort(-r);
index=index(sorted_most_content,:);
%Now first three columns of index should be unique and the best choice
%comes first, finally unique can be used.
[~,indices_unique_content,~]=unique(index(:,1:3),'rows');
%use previously appended consecutive numbers to get line numbers we want.
%sort restores original ordering.
unique_content_inorder=sort(index(indices_unique_content,4));
%The data you want:
M(unique_content_inorder,:)

Related

Maximize based on constraints

3 Arrays f1,f2 and f3 have child elements (f1a,f1b) ; (f2a,f2b,f2c) ; (f3a,f3b,f3c,f3d) respectively.They are all bool variables
I have a combination of these child elements in a list with 2 columns . The first column gives an ID and second col has the combination of child elements as shown below
row1 : 2345 | f1a , f2b
row2 : 2345 | f1a,f2a,f3c
row3 : 2346 | f2c, f3a
row4 : 2347 | f1b, f2c
.... ....
I need to choose one element of each of the arrays and form a selected array
if all elements of row are represented in selected array, I set 1 for that Row , else 0
So if selected array is [ f1a,f2a,f3c] , then ( using the above list example)
row1 is 0 ( as f2b is not in selected array)
row2 is 1 as all elements of row are in selected list
row3 is 0 as f2c and f3a is not in selected array
row4 is 0 as f2c is not present in selected array
I need to choose the selected array so as to maximize the sum of Row count (0+1+0+0 ...) for all Unique ID
for example if list is as shown below and selected array is [f1a,f2b,f3c] , though both rows are set 1 ,
I would only take 1 from both the rows as ID is same in both rows
row1 : 2345 | f1a , f2b
row2 : 2345 | f1a,f2b,f3c
Any help is appreciated as I am new to Minizinc and struggling to formulate the constraint with Minizinc
If your row variables are themselves also located in an array, then
solve maximize sum(row);
should set the activation of the rows to be the objective.
If you don't have them in an array you can still manually add them together to form an objective:
solve maximize row1 + row2 + row3 + row4;
I'm unsure if you were also asking about how the row activation itself works, but if a row only activates when all its elements are selected, then this would be enforced using a simple forall constraint:
constraint row1 = forall([...]);
I could finally get it working with this code. Here row1 and row2 have same ID and similarly row 3 and row4 have another common ID
array[1..2] of var bool: f1 ;
array[1..2] of var bool: f1 ;
array[1..3] of var bool: f2 ;
array[1..4] of var bool: f3 ;
var bool: row1;
var bool: row2 ;
var bool: row3 ;
var bool: row4 ;
constraint sum(f1) == 1;
constraint sum(f2) == 1;
constraint sum(f3) == 1;
constraint row1 = forall ( [(f1[1]) ] ) ;
constraint row2 = forall ( [(f1[2]) , (f2[2]) , (f3[3]) ] );
constraint row3 = forall ( [(f1[1]) , (f2[2]) , (f3[3]) ] ) ;
constraint row4 = forall ( [(f1[2]) , (f2[1]) , (f3[4]) ] ) ;
var int: rown1 = bool2int(row1) ;
var int: rown2 = bool2int(row2) ;
var int: rown2a = max(rown1,rown2) ;
var int: rown3 = bool2int(row3) ;
var int: rown4 = bool2int(row4) ;
var int: rown4a = max( rown3,rown4) ;
var int: rown = rown2a + rown4a ;
solve maximize rown;

In Netlogo, can a list of boolean variables be converted from true/false to 1/0?

I am creating a list of boolean values that represent a set of patches with the following code, where "obstacle" is a boolean property of the patch that says whether or not it is an obstacle and "map-area" is a list of specific patches.
set cell-walls map [ p -> [ obstacle ] of p] map-area
Then I print cell-walls to a text file, and it will print [ true true false true ... ].
I need it to print [ 1 1 0 1 ... ] instead.
Maybe I can replace elements in the list, or create a new list by iterating over this one and adding a 1 or 0 for each element. I'm not sure how to accomplish this in Netlogo. Help is appreciated! :)
If you only ever have true or false values, you could probably get away with something like:
to boolean-to-numeric
let bool [ true false true ]
let bool2 map [ i -> ifelse-value ( i = true ) [ 1 ] [ 0 ] ] bool
print bool2
end
But do note that the above will report 0 for any values other than true, not just for false.

Combine 2 rows in a cell array

I have a number of rows in a cell array with lots of extra space at the end of the rows as such:
'a' 'b' 'c' 'd' [] [] [] [] []
'1' '2' '3' [] [] [] [] [] []
'w' 'x' 'y' 'z' [] [] [] [] []
I would like to copy the second row onto the end of the first row, as such:
'a' 'b' 'c' 'd' '1' '2' '3' [] []
'1' '2' '3' [] [] [] [] [] []
'w' 'x' 'y' 'z' [] [] [] [] []
Please note that the code given above is an arbitrary example to demonstrate what I wish to do. In reality I will include this functionality as a step in a more complex function.
I have tried searching for the first empty element in the cell array row, but for some reason isempty does not see them as empty. Is there an alternative method that someone could point me towards?
EDIT:
After the steps carried out above, the second row will be deleted, giving:
'a' 'b' 'c' 'd' '1' '2' '3' [] []
'w' 'x' 'y' 'z' [] [] [] [] []
Although the real cell array will have many more rows than 3.
I think this does what you want. I've denoted your cell array as c.
n1 = find(cellfun('isempty',c(1,:)), 1); %// first empty cell in row 1
n2 = find(cellfun('isempty',c(2,:)), 1); %// first empty cell in row 2
c(1,n1:n1+n2-2) = c(2,1:n2-1); %// copy the relevant part of row 2 onto row 1
This automatically extends your cell horizontally if the number of non-empty cells in row 2 exceeds the number of empty cells in row 1.
Example: input:
c = {'a' 'b' 'c' 'd' [] [] [] [] []
'1' '2' '3' [] [] [] [] [] []
'w' 'x' 'y' 'z' [] [] [] [] []}
Output:
c =
'a' 'b' 'c' 'd' '1' '2' '3' [] []
'1' '2' '3' [] [] [] [] [] []
'w' 'x' 'y' 'z' [] [] [] [] []
Here's one general approach that uses the efficient logical indexing to select the non-empty cells, single call to cellfun('isempty' and does automatic extension as talked about in Luis's solution -
C = {
'a' 'b' 'c' 'd' [] [] [] [] []
'1' '2' '3' [] [] [] [] [] []
'w' 'x' 'y' 'z' [] [] [] [] []} %// Input cell array
N = 2; %//Number of rows to process, starting from 2 until the number of rows in C
Ct = C'; %//'# Transpose input cell array, as collecting elements that way is easier
vals = Ct(~cellfun('isempty',Ct(:,1:N))); %//'# elements from selected row(s)
C(1,1:numel(vals)) = vals; %// Place the values into the first row
With N = 2 which is the case stated in the problem, output would be -
C =
'a' 'b' 'c' 'd' '1' '2' '3' [] []
'1' '2' '3' [] [] [] [] [] []
'w' 'x' 'y' 'z' [] [] [] [] []
With N = 3, you would copy the second and third rows at the end of the first row. Thus, the output would be -
C =
'a' 'b' 'c' 'd' '1' '2' '3' 'w' 'x' 'y' 'z'
'1' '2' '3' [] [] [] [] [] [] [] []
'w' 'x' 'y' 'z' [] [] [] [] [] [] []
and so on.

how to edit cells array in matlab

I have this cells array which is came from a mat lab code that generates dewey IDs:
POT1 =
'a0' [] [] []
'a0' 'c0' [] []
'a0' 'b0' [] []
'a0' 'c1' [] []
'a0' 'd0' [] []
'a0' 'c0' 'd1' []
'a0' 'b0' 'd2' []
'a0' 'd0' 'd3' []
'a0' 'd0' 'c2' []
'a0' 'd0' 'b1' []
'a0' 'd0' 'd4' []
'a0' 'c1' 'c3' []
'a0' 'c1' 'b2' []
'a0' 'c1' 'c3' 'd5'
'a0' 'c1' 'b2' 'd6'
'a0' 'd0' 'b1' 'd7'
'a0' 'd0' 'c2' 'd8'
note that column 1 is parent of column 2 and column 2 is paret of column 3..etc
so I want to build a code that gives the full name of each cell as follow:
POT1 =
a0 [] [] []
a0 a0.c0 [] []
a0 a0.b0 [] []
a0 a0.c1 [] []
a0 a0.d0 [] []
a0 a0.c0 a0.c0.d1 []
a0 a0.b0 a0.b0.d2 []
a0 a0.d0 a0.d0.d3 []
a0 a0.d0 a0.d0.c2 []
a0 a0.d0 a0.d0.b1 []
.
.
.
.
The code which I build is not complete and gives me :" Index exceeds matrix dimensions" error :
for i=1:length(POT1)
for j=3:size(POT1,2)
if ~isempty(POT1{i,j})
POT1{i,j}=[POT1{i,j-2} POT1{i,j-1} POT1{i,j}];
end
end
end
POT1
I think you're on the right track, but it's easier if you process it column by column. This way, you just have to look one column back for each entry:
for jj=2:size(POT1,2)
for ii=1:size(POT1,1)
if ~isempty(POT1{ii,jj})
POT1{ii,jj}=[POT1{ii,jj-1} '.' POT1{ii,jj}];
end
end
end
btw: length returns the Length of vector or largest array dimension, so next time, better use size.
If you have vectors with ' %Two spaces ' on the empty spaces it will be really easy.
You can just transform it into a matrix and the rest is simple as this:
[POT1(:,1:2) '.' POT1(:,3:4)]
Afterwards you can just strip the spaces and done.

Replace strings with integer IDs in a Cell - Matlab

I have a cell that has string IDs. I need to replace them with integer IDs so that the cell can be transformed into a matrix. I especially need this to be a vectorized operation as the celldata is huge.
celldata = { 'AAPL' [0.1] ; 'GOOG' [0.643] ; 'IBM' [0.435] ; 'MMM' [0.34] ; 'AAPL' [0.12] ; 'GOOG' [1.5] ; 'IBM' [0.75] ; 'AAPL' [0.56] ; 'GOOG' [0.68] ; 'IBM' [0.97] ; };
I designed a sequential intID:
intIDs = {'AAPL' [1] ; 'GOOG' [2] ; 'IBM' [3] ; 'MMM' [4]};
intIDs contain ALL IDs that are possible in celldata. Also, celldata has IDs in sequential order and grouper together by dates. The date column is not shown here.
Desired result:
celldata = {[1] [0.1] ; [2] [0.643] ; [3] [0.435] ; [4] [0.34] ; [1] [0.12] ; [2] [1.5] ; [3] [0.75] ; [1] [0.56] ; [2] [0.68] ; [3] [0.97] ;};
Thanks!
You can use the ismember function and logical indexing to achieve what you want.
[~,indx]=ismember(celldata(:,1),intIDs(:,1));
celldata(:,1)=intIDs(indx,2)
celldata =
[1] [0.1000]
[2] [0.6430]
[3] [0.4350]
[4] [0.3400]
[1] [0.1200]
[2] [1.5000]
[3] [0.7500]
[1] [0.5600]
[2] [0.6800]
[3] [0.9700]