Remove rows from a matrix - matlab

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),:)

Related

How to insert a structure within a structure

I have a 1x1 structure called imu_data.txyzrxyz1. It has one field called txyzrxyz1 and the value is 4877x7 double. I just want to "copy and paste" row 62 into row 63 (double up that row) so that the structure now becomes a 4878x7 structure. I've tried the following, with other versions without success:
extra_63 = imu_data.txyzrxyz1(63,:);
imu_data2.txyzrxyz1 = [{imu_data.txyzrxyz1(1:62,:) extra_63 imu_data.txyzrxyz1(63:end,:)}]
Thanks
You can index the row to duplicate twice while matrix indexing:
row_to_duplicate = 63;
yourdata = rand(100,10);
yourstruct.data = yourdata;
yourstruct.data = yourstruct.data([1:row_to_duplicate, row_to_duplicate:end],:)
So in case of 63, 1:row_to_duplicate will create a column vector from 1:63, and row_to_duplicate:end will create a column vector from 63:100 in this example. When combining these, 63 will occur twice, hence that row is duplicated.
You were almost there, you only had to get rid of the {}'s and put the data in the right orientation by using ; instead of a space between matrix entries to vertically concatenate instead of horizontally:
extra_63 = imu_data.txyzrxyz1(63,:);
imu_data2.txyzrxyz1 = [imu_data.txyzrxyz1(1:62,:); extra_63; imu_data.txyzrxyz1(63:end,:)]

How to add values to last column of a table based on certain conditions in MATLAB?

I have a 29736 x 6 table, which is referred to as table_fault_test_data. It has 6 columns, with names wind_direction, wind_speed, air_temperature, air_pressure, density_hubheight and Fault_Condition respectively. What I want to do is to label the data in the Fault_Condition (last table column with either a 1 or a 0 value, depending on the values in the other columns.
I would like to do the following checks (For eg.)
If wind_direction value(column_1) is below 0.0040 and above 359.9940, label 6 th column entry corresponding to the respective row of the table as a 1, else label as 0.
Do this for the entire table. Similarly, do this check for others
like air_temperature, air_pressure and so on. I know that if-else
will be used for these checks. But, I am really confused as to how I
can do this for the whole table and add the corresponding value to
the 6 th column (Maybe using a loop or something).
Any help in this
regard would be highly appreciated. Many Thanks!
EDIT:
Further clarification: I have a 29736 x 6 table named table_fault_test_data . I want to add values to the 6 th column of table based on conditions as below:-
for i = 1:29736 % Iterating over the whole table row by row
if(1st column value <x | 1st column value > y)
% Add 0 to the Corresponding element of 6 th column i.e. table_fault_test_data(i,6)
elseif (2nd column value <x | 2nd column value > y)
% Add 0 to the Corresponding element of 6 th column i.e. table_fault_test_data(i,6)
elseif ... do this for other cases as well
else
% Add 1 to the Corresponding element of 6 th column i.e. table_fault_test_data(i,6)
This is the essence of my requirements. I hope this helps in understanding the question better.
You can use logical indexing, which is supported also for tables (for loops should be avoided, if possible). For example, suppose you want to implement the first condition, and also suppose your x and y are known; also, let us assume your table is called t
logicalIndecesFirstCondition = t{:,1} < x | t{:,2} >y
and then you could refer to the rows which verify this condition using logical indexing (please refer to logical indexing
E.g.:
t{logicalIndecesFirstCondition , 6} = t{logicalIndecesFirstCondition , 6} + 1.0;
This would add 1.0 to the 6th column, for the rows for which the logical condition is true

Rows without repetitions - MATLAB

I have a matrix (4096x4) containing all possible combinations of four values taken from a pool of 8 numbers.
...
3 63 39 3
3 63 39 19
3 63 39 23
3 63 39 39
...
I am only interested in the rows of the matrix that contain four unique values. In the above section, for example, the first and last row should be removed, giving us -
...
3 63 39 19
3 63 39 23
...
My current solution feels inelegant-- basically, I iterate across every row and add it to a result matrix if it contains four unique values:
result = [];
for row = 1:size(matrix,1)
if length(unique(matrix(row,:)))==4
result = cat(1,result,matrix(row,:));
end
end
Is there a better way ?
Approach #1
diff and sort based approach that must be pretty efficient -
sortedmatrix = sort(matrix,2)
result = matrix(all(diff(sortedmatrix,[],2)~=0,2),:)
Breaking it down to few steps for explanation
Sort along the columns, so that the duplicate values in each row end up next to each other. We used sort for this task.
Find the difference between consecutive elements, which will catch those duplicate after sorting. diff was the tool for this purpose.
For any row with at least one zero indicates rows with duplicate rows. To put it other way, any row with no zero would indicate rows with no duplicate rows, which we are looking to have in the output. all got us the job done here to get a logical array of such matches.
Finally, we have used matrix indexing to select those rows from matrix to get the expected output.
Approach #2
This could be an experimental bsxfun based approach as it won't be memory-efficient -
matches = bsxfun(#eq,matrix,permute(matrix,[1 3 2]))
result = matrix(all(all(sum(matches,2)==1,2),3),:)
Breaking it down to few steps for explanation
Find a logical array of matches for every element against all others in the same row with bsxfun.
Look for "non-duplicity" by summing those matches along dim-2 of matches and then finding all ones elements along dim-2 and dim-3 getting us the same indexing array as had with our previous diff + sort based approach.
Use the binary indexing array to select the appropriate rows from matrix for the final output.
Approach #3
Taking help from MATLAB File-exchange's post combinator
and assuming you have the pool of 8 values in an array named pool8, you can directly get result like so -
result = pool8(combinator(8,4,'p'))
combinator(8,4,'p') basically gets us the indices for 8 elements taken 4 at once and without repetitions. We use these indices to index into the pool and get the expected output.
For a pool of a finite number this will work. Create is unique array, go through each number in pool, count the number of times it comes up in the row, and only keep IsUnique to 1 if there are either one or zero numbers found. Next, find positions where the IsUnique is still 1, extract those rows and we finish.
matrix = [3,63,39,3;3,63,39,19;3,63,39,23;3,63,39,39;3,63,39,39;3,63,39,39];
IsUnique = ones(size(matrix,1),1);
pool = [3,63,39,19,23,6,7,8];
for NumberInPool = 1:8
Temp = sum((matrix == pool(NumberInPool))')';
IsUnique = IsUnique .* (Temp<2);
end
UniquePositions = find(IsUnique==1);
result = matrix(UniquePositions,:)

Remove leading column values <= 0

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)

Using SUM and UNIQUE to count occurrences of value within subset of a matrix

So, presume a matrix like so:
20 2
20 2
30 2
30 1
40 1
40 1
I want to count the number of times 1 occurs for each unique value of column 1. I could do this the long way by [sum(x(1:2,2)==1)] for each value, but I think this would be the perfect use for the UNIQUE function. How could I fix it so that I could get an output like this:
20 0
30 1
40 2
Sorry if the solution seems obvious, my grasp of loops is very poor.
Indeed unique is a good option:
u=unique(x(:,1))
res=arrayfun(#(y)length(x(x(:,1)==y & x(:,2)==1)),u)
Taking apart that last line:
arrayfun(fun,array) applies fun to each element in the array, and puts it in a new array, which it returns.
This function is the function #(y)length(x(x(:,1)==y & x(:,2)==1)) which finds the length of the portion of x where the condition x(:,1)==y & x(:,2)==1) holds (called logical indexing). So for each of the unique elements, it finds the row in X where the first is the unique element, and the second is one.
Try this (as specified in this answer):
>>> [c,~,d] = unique(a(a(:,2)==1))
c =
30
40
d =
1
3
>>> counts = accumarray(d(:),1,[],#sum)
counts =
1
2
>>> res = [c,counts]
Consider you have an array of various integers in 'array'
the tabulate function will sort the unique values and count the occurances.
table = tabulate(array)
look for your unique counts in col 2 of table.