Remove leading column values <= 0 - matlab

I have some input such like:
a = -1.60400000000000,-0.604000000000000,0.396000000000000,1.39600000000000,2.39600000000000,3.39600000000000,4.39600000000000,5.39600000000000,6.39600000000000,7.39600000000000
And I want to remove the columns with a value which is negative / 0.
I have tried the following:
a = max(a, 0);
a = a(:,a(:,:)>0);
But to no avail.
Any suggestions also using linear indexing?
Thanks.

Another way to remove elements (besides reassigning the array) is by assigning [] to the elements you want removed. For a 1D row/column vector
a(a<=0) = []
It's not clear what is needed for a matrix, but say you want to remove the columns for which all values in that column are negative:
a(:,all(a<=0,1)) = []
Or if you want to remove columns with any negative values:
a(:,any(a<=0,1)) = []
In order to treat the first element/row of each column as the indicator for removing the entire column:
a(:,a(1,:)<=0) = []
For example:
>> a=rand(5)-0.5
a =
0.0822 -0.3808 0.0447 0.4937 -0.0954
0.0407 0.4398 0.1473 -0.2813 -0.0516
0.3699 0.1456 0.0439 -0.3942 -0.1342
-0.2352 -0.0205 0.2210 -0.3903 0.2635
-0.1819 0.1393 0.0225 -0.4364 0.1279
>> a(:,a(1,:)<=0) = []
a =
0.0822 0.0447 0.4937
0.0407 0.1473 -0.2813
0.3699 0.0439 -0.3942
-0.2352 0.2210 -0.3903
-0.1819 0.0225 -0.4364

for your example you can just use
a(a>0)

Related

Remove rows from a matrix

I have the array "A" with values:
101 101
0 0
61.6320000000000 0.725754779522671
73.7000000000000 0.830301150185882
78.2800000000000 0.490917508345341
81.2640000000000 0.602561200211232
82.6880000000000 0.435568593909153
And I wish to remove this first row and retain the shape of the array (2 columns), thus creating the array
0 0
61.6320000000000 0.725754779522671
73.7000000000000 0.830301150185882
78.2800000000000 0.490917508345341
81.2640000000000 0.602561200211232
82.6880000000000 0.435568593909153
I have used A = A(A~=101); , which removes the values as required - however it packs the array down to one column.
The best way is:
A = A(2:end, :)
But you can also do
A(1,:) = []
however it is slightly less efficient (see Deleting matrix elements by = [] vs reassigning matrix)
If you are looking to delete rows that equal a certain number try
A = A(A(:,1)~=101,:)
Use all or any if you want to delete row if either all or any column equals your value:
A = A(all(A~=101,2),:)

MatLab: Find numeric values in cell array

In my cell array test = cell(1,2,20,14); I want to find numeric values in the subset test(:,1,1,1).
For example test(:,:,1,1) looks like this:
>> test(:,:,1,1)
ans =
[ 0] [0.1000] [57]
[0.9000] [0.9500] [73]
I want to find the index of the cell containing 0.9 in the first column, so I can access the third column (in this case value 73). I tried:
find(test{:,:,1,1} == 0.9) which gives:
Error using == Too many input arguments..
How can I find the respective index?
Thanks.
Try this to access that third column value directly -
cell2mat(test(vertcat(test{:,1,1,1})==0.9,3,1,1))
Edit 1: If you would like to test out for match w.r.t. the first two columns of test's subset, use this -
v1 = reshape(vertcat(test{:,[1 2],1,1}),[],2)
cell2mat(test(ismember(v1,[0.9 0.95],'rows'),3,1,1))
Just add brackets [] around test{:,:,1,1}. This wraps the different cell values together to one vector/matrix.
Like this:
[index1, index2] = find([test{:,:,1,1}] == 0.9)

Select rows whose values in one column match specfic vector

First my question seemed easy, but i still can't find relevant answer to it.
So I have matrix with size of mx4
a = [(2:6)' rand(5,3)]
a =
2. 0.1589990 0.2725595 0.2944531
3. 0.0181815 0.3437655 0.5718074
4. 0.4098371 0.2033702 0.2141770
5. 0.0105835 0.3011945 0.6895462
6. 0.1965310 0.2762596 0.5855573
And vector b with size of mx1. Elements of b always can be find in the first column of a. For example:
b = [2;3;6]
What I want is to select rows whose value in first column matches values of b, i.e.
ans =
2. 0.1589990 0.2725595 0.2944531
3. 0.0181815 0.3437655 0.5718074
6. 0.1965310 0.2762596 0.5855573
All I've come with so far are these solutions:
Ans(1,:) = a(a(:,1)==b(1),:);
Ans(2,:) = a(a(:,1)==b(2),:);
Ans(3,:) = a(a(:,1)==b(3),:);
And slightly automatized version:
Ans = zeros(size(b,1),size(a,2));
for i = 1:size(b,1)
Ans(i,:)=a(a(:,1)==b(i),:)
end
Is there any possibility to make it easy, may be in one line or without loop?
I think ismember is your friend here:
a = [(2:6)' rand(5,3)]
b = [2;3;6]
a(ismember(a(:,1),b),:)
a =
2.000000 0.065121 0.172047 0.490842
3.000000 0.585701 0.650922 0.260139
4.000000 0.266305 0.543419 0.562515
5.000000 0.760789 0.378180 0.560597
6.000000 0.058769 0.926874 0.538872
b =
2
3
6
ans =
2.000000 0.065121 0.172047 0.490842
3.000000 0.585701 0.650922 0.260139
6.000000 0.058769 0.926874 0.538872
Thanks to RTL for noting that a(ismember(a,b),:) might match elements that were not in the first column.
This -
out = a(find(sum(squeeze(any(bsxfun(#eq,a,permute(b,[3 2 1])),2)),2)),:)
Wow, that's a huge thing isn't it!
Slightly shorter -
out = a(any(squeeze(bsxfun(#eq,a(:,1),permute(b,[3 2 1]))),2),:)
And shorterer -
out = a(any(bsxfun(#eq,a(:,1),b'),2),:)
Without bsxfun or ismember? Hmm..try out intersect, that is basically similar to ismember -
[~,ind,~] = intersect(a(:,1),b);
out = a(ind,:)

Remove data from struct bigger than a certain value

I have a struct, that's a <1x1 struct>, and I'm trying to edit a field in the struct based on the values. The field is called GeoDist_Actual and the struct is called GeoDist_str. The field GeoDist_Actual is a <262792x1 double>, and this is the code I was trying to use in order to get rid of the values that are greater than 1.609344e+05.
i =1;
for i=i:size(GeoDist_str.GeoDist_Actual)
if GeoDist_str.GeoDist_Actual(i,1 > 1.609344e+05
GeoDist_str.GeoDist_Acutal(i,1) = [];
end
end
How would I append or alter this code in order to make it function like I'm aiming? I considered setting all the values to 0, but I'm going to have to go backwards from this in order to get back GPS values, doing a reverse-Vincenty(spherical) calculation, and I'd like to just completely get rid of the values that don't comply with the if condition.
If I can narrow down the question at all, let me know, and thank you for your help in advance!
Edit: I've noticed that when I changed out the section
GeoDist_str.GeoDist_Actual(i,1) = [];
for
GeoDist_str.GeoDist_Actual(i,1) = 0;
It didn't actually solve anything, instead it didn't access the field "GeoDist_Actual" within the struct "GeoDist_str", it just created a mirror field with values of 0.
Consider this example:
% a 10-by-1 vector
x = [1;2;3;4;5;6;7;8;9;10];
% remove entries where the value is less than five
x(x<5) = [];
This is called logical indexing, no need for loops.
Consider the following simple example:
A.a = 1:5;
A =
a: [1 2 3 4 5]
now delete all elements bigger 3;
A.a = A.a( ~(A.a > 3) );
A =
a: [1 2 3]
or alternatively:
A.a( A.a > 3 ) = []
For your case it's a little more bulky:
GeoDist_str.GeoDist_Actual = ...
GeoDist_str.GeoDist_Actual( ...
~(GeoDist_str.GeoDist_Actual > 1.609344e+05) )

Complementary array Matlab

We've got an array of values, and we would like to create another array whose values are not in the first one.
Example:
load('internet.mat')
The first column contains the values in MBs, we have thought in something like:
MB_no = setdiff(v, internet(:,1))
where v is a 0 vector whose length equals to the number of rows in internet.mat. But it just doesn't work.
So, how do we do this?
You need to specify the range of possible values to define what values are not in internet . Say the range is v = 1:10 then setdiff(v,internet(:,1)) will give you the values in 1:10 that are not in the first column of internet.
It seems as if you don't want the first column.
You can simply do:
MB_no=internet(:,2:end);
assuming internet(:,1) has only positive integers and you wish to find which are the integers in [1,...,max( internet(:,1) )] that do not appear in that range you can simply do
app = [];
app( internet(:,1) ) = 1;
MB_no = find( app == 0 );
This is somewhat like bucket sort.