MATLAB: removing some of the elements of a matrix - arrays

I have a matrix that looks like :
A =[
1 5
2 10
3 12
4 25
5 8]
Let's assume that I want to remove the rows that contain elements that are larger than 10. I have been trying to use a for loop and simply read the matrix and use
for ii = 1:5
for jj = 2
if A(ii,jj) > 10
A(ii,2) = [];
end
end
end
The problem is that, I keep receiving errors regarding the size of a matrix. As one row is deleted, the size of the matrix is reduced and I know that I have to set size(A)=size(A)-1 but it doesn't work. Any help is appreciated!

You can't remove a single element when using subscript notation, so your error is here:
A(i,2) = [];
You have two choices, either remove the entire row:
A(i,:) = [];
or else linearise your matrix and remove single elements (but then you won't be able to recover you original shape:
for ii = numel(A):-1:1
if A(ii) > 10
A(ii) = [];
end
end
but using a loop for this is unnecessary and probably inefficient. You can do it using logical indexing like so:
A(any(A'>10),:) = [];
to remove the whole row or else to just remove single elements try:
A(A>10) = []
but then you'll see that you end up with a row vector (linearized) result

Here is a solution, quite similar to the one of #Dan. Basically this keeps what you want instead of removing what you don't want:
A(all(A<=10,2),:)

Related

Matlab: Storing an array in a matrix within a for loop

I'm running a for loop which outputs a (100x2) array which is called AFdata. For every loop iteration, I want to save AFdata in AFmat. However I cannot solve the algorithm to for the columns so that every AFdata of every iteration fills the right spot in AFmat.
This is code I am using now:
for i = 1:Nsections
AFdata = Airfoil.getDatFile(Input.airfoilList{i},airfoilDir);
if isfield(Input,'TcRatios') && ~isempty(Input.TcRatios)
AFdata(:,2) = AFdata(:,2)*(Input.TcRatios(i)...
/Airfoil.calculateThickness(AFdata(:,2)));
end
end
for example:
the first iteration gives AFdata = [1 0; 2 0; 3 0]
the second iteration gives AFdata = [4 9; 6 9; 8 9]
and thus after 2 iterations, AFmat should be [1 0 4 9; 2 0 6 9 ;3 0 8 9]
thanks!!!
Pre-allocate AFmat with required size first and then fill appropriate columns at each iteration, e.g.
AFmat = zeros(100, 2*Nsections);
for i = 1:Nsections
% ... calc AFdata
AFmat(:,[2*i-1,2*i]) = AFdata;
end
You can use cat() function. Declare AFmat as a blank matrix (if you don't know the exact dimension) and just concatenate afterwards.
AFmat=[];
for i = 1:Nsections
%calculate AFdata...............
AFmat=cat(2,AFmat,AFdata);
end
I've heard comments that this affects the code performance (not allocating the matrix) but MATLAB doesn't complain. I personally like this because the dimension in the cat() function feels easy to me to control the final matrix property.

multidimensional cell array in Matlab

I'v 3 cell arrays of same number of cells, However I want to reduce in only one cell array having multiple dimensions so that they can be access by column wise like array's column. I'm working in Matlab's environment, However I'v tried to do so, but unfortunately I'v found no cell access as column as in matrices. Any Suggestions for handle such case?
My Code:
P = cell(1,10);
Pd = cell(1,10);
Pdd = cell(1,10);
for ii=1:10
P{ii}= [repmat([0 0 0],2,1)];
Pd{ii} = [repmat([1 1 1],2,1)];
Pdd{ii} = [repmat([2 2 2],2,1)];
end
Concatenate the three cell arrays vertically:
Pall = [P; Pd; Pdd]
This gives a 3x10 cell array Pall, such that Pall(1,:) is P, etc.
If you want to avoid creating multiple cell arrays from the beginning: do something similar to this:
for ii=1:10
Pall{1,ii}= [repmat([0 0 0],2,1)];
Pall{2,ii} = [repmat([1 1 1],2,1)];
Pall{3,ii} = [repmat([2 2 2],2,1)];
end
To avoid loops, with the values in your example:
Pall = mat2cell(repmat([repmat([0 0 0],2,1); repmat([1 1 1],2,1); repmat([2 2 2],2,1)],1,10),[2 2 2],3*ones(1,10))

Concatenating 1D matrices of different sizes

I perhaps am going about this wrong, but I have data{1}, data{2}...data{i}. Within each, I have .type1, .type2.... .typeN. The arrays are different lengths, so horizontal concatenation does not work.
For simplicity sake
>> data{1}.type1
ans =
1
2
3
>> data{2}.type1
ans =
2
4
5
6
Results should be [1;2;3;2;4;5;6]
I've been trying to loop it but not sure how? I will have a variable number of files (a,b..). How do I go about looping and concatenating? Ultimately I need a 1xN array of all of this..
My working code, thanks..figured it out..
for i = 1:Types
currentType = nTypes{i}
allData.(currentType)=[];
for j = 1:nData
allData.(currentType) = [allData.(currentType); data{j}.(currentType)(:,3)]; %3rd column
end
end
Look at cat, the first argument is the dimension. In your simple example it would be:
result = cat(1,a,b);
Which is equivalent to:
result = [a;b];
Or you can concatenate them as row vectors and transpose back to a column vector:
result = [a',b']';
For the case of a structure inside a cell array I don't think there will be any way around looping. Let's say you have a cell array with M elements and N "types" as the structure fields for each element. You could do:
M=length(data);
newData=struct;
for i=1:M
for j=1:N
field=sprintf('type%d',j); % //field name
if (M==1), newData.(field)=[]; end % //if this is a new field, create it
newData.(field)=[newData.(field);data{i}.(field)];
end
end

Turning an array in to a matrix in MATLAB

I need to turn a large array into a matrix in the following way: to take the first m entries of the array and make that the 1st row of the matrix.
For example: if I had an array that was 100 entries long, the corresponding matrix would be 10 rows and each row would be 10 entries of the array with the order preserved.
I've tried the following code:
rows = 10
row_length = 10
a = randi(1,100);
x = zeros(rows,row_length)
for i=1:rows
x(i) = a(i:i+row_length)
end
but with no luck. I'm stuck on how to slide the window along by row_length so that i will start from row_length+1 in the second (and subsequent) iterations of the loop.
The best way to do it is to use Matlab's reshape function:
reshape(a,row_length,[]).'
It will reshape by first assigning down the columns which is why I transpose at the end (i.e. .')
However just for the sake of your learning, this is how you could have done it your way:
rows = 10
row_length = 10
a = rand(1,100)
x = zeros(rows,row_length)
for i=1:row_length:rows*row_length %// use two colons here, the number between them is the step size
x(i:i+row_length-1) = a(i:i+row_length-1) %// You need to assign to 10 elements on the left hand side as well!
end

Matlab Assigning Elements to Array in loop

I have this loop which generates a vector "Diff". How do I place the values of Diff in an array that records all the Diff's generated? The problem is that the length of Diff should be a fixed length (36) which is the width of the table "CleanPrice". But because col_set varies in length (according to the number of NaNs in the data it is reading), then Diff also varies in length. What I need it to do is assign the answers generated according to their appropriate column number. i.e. row(i) of diff should contain col(i) where all other rows in Diff should be assigned a "0" or "NaN". Basically I need DiffArray to be a (nTrials x 36) array where each row is the (36 x 1) DiffArray generated. At the moment though, each time the length of col changes, I get the following error:
??? Subscripted assignment dimension mismatch.
Error in ==> NSSmodel
at 41 DiffMatrix(end+1,:)=Diff
This is my code:
DiffArray=[];
StartRow=2935;
EndRow=2940;
nTrials=EndRow-StartRow;
for row=StartRow:EndRow;
col_set=find(~isnan(gcm3.data.CleanPrice(row,1:end)));
col=col_set(:,2:end);
CleanPrices=transpose(gcm3.data.CleanPrice(row,col));
Maturity=gcm3.data.CouponandMaturity(col-1,2);
SettleDate=gcm3.data.CouponandMaturity(row,3);
Settle = repmat(SettleDate,[length(Maturity) 1]);
CleanPrices =transpose(gcm3.data.CleanPrice(row,col));
CouponRate = gcm3.data.CouponandMaturity(col-1,1);
Instruments = [Settle Maturity CleanPrices CouponRate];
PlottingPoints = gcm3.data.CouponandMaturity(1,2):gcm3.data.CouponandMaturity(36,2);
Yield = bndyield(CleanPrices,CouponRate,Settle,Maturity);
SvenssonModel = IRFunctionCurve.fitSvensson('Zero',SettleDate,Instruments)
ParYield=SvenssonModel.getParYields(Maturity);
[PriceActual, AccruedIntActual] = bndprice(Yield, CouponRate, Settle, Maturity);
[PriceNSS, AccruedIntNSS] = bndprice(ParYield, CouponRate, Settle, Maturity);
Diff=PriceActual-PriceNSS
DiffArray(end+1,:)=Diff
end
I looked at num2cell in this post but wasn't sure how to apply it correctly and started getting errors relating to that instead.
Is it correct to say you want to add an 'incomplete' row to DiffArray? If you know exactly where each element should go you could maybe do something like this:
indices = [1:7; 2:8; 3:9; [1 2 3 6 7 8 10]];
Diff = rand(4, 7);
DiffArray = zeros(4, 10) * NaN;
for row = 1:4
DiffArray(row, indices(row, :)) = Diff(row,:);
end
of course in your case you would be calculating Diff and Index (a row vector) inside the loop and not using preassigned arrays. The above is just to illustrate how to use an indexing vector to position a short row in a matrix.

Resources