Duplicate table value to have the same size - matlab

I have two tables of different size. I'm using Matlab, it doesn't matter I just need the logic of doing this
the first table contains 8 elements the second one contains 3
0.04 0.1
0.08 0.2
0.12 0.3
0.16
0.20
0.24
0.28
0.32
I want to compare the two tables, repeating same value in the second table while tab1(i) < tab2(i) in order to get two tables of the same size the result must be like this
0.04 0.1
0.08 0.1
0.12 0.2
0.16 0.2
0.20 0.2
0.24 0.3
0.28 0.3
0.32 0.0
i've tried this
for ii=1:sizex1(1)
for jj=1:ssimagefile
if x2imagefile(jj)<=z1(ii)
tab2(ii)=z1(ii)
fprintf(file, '%f %f \n', [ii tab2]');
jj=jj+1;
else
ii=ii+1;
end
end

Here is a Matlaby way to do it:
%// Add zeros to the end of tab2 so that it is as long as tab1
tab3(numel(tab1)) = 0;
%// use bsxfun to find for each number, which rows it will be replicated into
I = bsxfun(#le, tab1, tab2') & bsxfun(#gt, tab1, [-inf,tab2(1:end-1)']);
%// use find to convert the rows from the step before to indexes of where the numbers lie in tab1
[~,c] = find(I);
%// populate tab3 with the repeated numbers from tab2
tab3(1:numel(c)) = tab2(c);
And a simpler way using for loops:
tab3 = zeros(size(tab1));
for row = 1:numel(tab1)
idx = tab2 > tab1(row);
if any(idx)
tab3(row) = min(tab2(idx));
end
end

You could also take the following vectorized approach in case you prefer to avoid bsxfun:
tab2_sorted = sort(tab2); % Sort tab2
tab3=zeros(size(tab1)); % Initialize the new table
% Fill the new table with the values of tab2
tab3(tab1<=tab2_sorted(3))=tab2_sorted(3);
tab3(tab1<=tab2_sorted(2))=tab2_sorted(2);
tab3(tab1<=tab2_sorted(1))=tab2_sorted(1);

Related

How to select whole numbers in a row and its adjacent numbers in Matlab

Good day!
I would like to select the whole numbers in my random data, at the same time it will also choose the adjacent numbers.
For example, I have this raw data
A = [0.1 0.2
0.2 0.1
1 0.3
0.3 0.2
0.4 0.4
2 0.5]
so would like to select the (1, 0.3) and (2, 0.5). then my final ouptut will be,
B= [1 0.3
2 0.4]
Thanks in advance!
You can use modulo:
B=A(sum(mod(A,1),2)==0,:)
========== EDIT ====================
Editing w.r.t. comments, if you are only checking for integers in the first column then you do not need to sum results:
B=A(mod(A(:,1),1)==0,:)
Alternative ways would use logicals instead of numericals:
B=A(all(A==round(A),2),:)
or if only the 1st column is checked:
B=A(A==round(A(:,1)),:)

Merge different sized arrays into a table

Overview
I am currently working with a series of .txt files I am importing into MATLAB. For simplicity, I'll show my problem conceptually. Obligatory, I'm new to MATLAB (or programming in general).
These .txt files contain data from tracking a ROI in a video (frame-by-frame) with time ('t') in the first column and velocity ('v') in the second as shown below;
T1 = T2 = etc.
t v t v
0 NaN 0 NaN
0.1 100 0.1 200
0.2 200 0.2 500
0.3 400 0.3 NaN
0.4 150
0.5 NaN
Problem
Files differ in their size, the columns remain fixed but the rows vary from trial to trial as shown in T1 and T2.
The time column is the same for each of these files so I wanted to organise data in a table as follows;
time v1 v2 etc.
0 NaN NaN
0.1 100 200
0.2 200 500
0.3 400 NaN
0.4 150 0
0.5 NaN 0
Note that I want to add 0s (or NaN) to end of shorter trials to fix the issue of size differences.
Edit
Both solutions worked well for my dataset. I appreciate all the help!
You could import each file into a table using readtable and then use outerjoin to combine the tables in the way that you would expect. This will work if all data starts at t = 0 or not.
To create a table from a file:
T1 = readtable('filename1.dat');
T2 = readtable('filename2.dat');
Then to perform the outerjoin (pseudo data created for demonstration purposes).
t1 = table((1:4)', (5:8)', 'VariableNames', {'t', 'v'});
%// t v
%// _ _
%// 1 5
%// 2 6
%// 3 7
%// 4 8
% t2 is missing row 2
t2 = table([1;3;4], [1;3;4], 'VariableNames', {'t', 'v'});
%// t v
%// _ _
%// 1 1
%// 3 3
%// 4 4
%// Now perform an outer join and merge the key column
t3 = outerjoin(t1, t2, 'Keys', 't', 'MergeKeys', true)
%// t v_t1 v_t2
%// _ ____ ____
%// 1 5 1
%// 2 6 NaN
%// 3 7 3
%// 4 8 4
I would suggest the use of the padarray and horzcat functions. They respectively :
Pad a matrix or vector with extra data, effectively adding extra 0's or any specified value (NaNs work too).
Concatenate matrices or vectors horizontally.
First, try to obtain the length of the longest vector you have to concatenate. Let's call this value max_len. Once you have that, you can then pad each vector by doing :
v1 = padarray(v1, max_len - length(v1), 0, 'post');
% You can replace the '0' by any value you want !
Finally, once you have vectors of the same size, you can concatenate them using horzcat :
big_table = horzcat(v1, v2, ... , vn);

find common values of all rows of a matrix

I have a random generated matrix
A =[ 0.7015 -1.577 -1.333 0.022 -0.5 -2.00 -0.034 -0.714
-2.05 -0.5 1.12 -0.26 -0.97 0.96 -0.79 1.35
-0.353 0.28 -0.5 -1.75 -1.15 0.52 1.018 -0.22
-0.8 0.033 -0.29 -0.28 -0.5 -0.02 -0.13 -0.58 ]
I want to find the common values of all rows.Each row has no duplicated elements. Can anyone give me a help?
Get a vector of unique values with unique, and then compare each element of A with each unique value using bsxfun:
u = unique(A);
m = squeeze(all(any(bsxfun(#eq, A, permute(u, [2 3 1])),2),1));
result = u(m);
This should be fast, but may be memory-hungry, as it generates a 3D array of size mxnxp, where A is mxn and p is the number of unique values of A. It works even if a row can contains duplicated elements.
Exploiting the fact that each row has no duplicated elements, you can use a possibly more memory-eficient approach with accumarray:
[u, ~, w] = unique(A);
m = accumarray(w,1)==size(A,1);
result = u(m);

access columns of row at index matlab

I have a text file A with N rows and 8 columns (example below):
1 2 0.02 0.28 0.009 0.04 0.03 0.16
2 4 0.04 0.21 0.4 0.04 0.03 0.13
if my variables x=2 and y=4 (I get during the program run -values change with every run.)
I know the index of the row I need to get:
rIndex = find((A{1}==x)&(A{2}==y));
here rindex = 2.
I need to access row at rIndex and do operation with columns 3 to 8 in that row. i.e. i get values from another file based on x and y and divide those values by column values at rIndex row.
x_No = 5, y_No = 6;
B = horzcat((x_No-y_No)./A{3}(1),(x_No-y_No))./A{4}(1),(x_No-y_No)./A{5}(1),(x_No-y_No)./A{6}(1),(x_No-y_No)./A{7}(1),(x_No-y_No)./A{8}(1));
What B does right now is operates on all rows from A. I need only at particular rIndex.
Its still not really clear what happens, but I think you can try something like this:
for r = 1:numel(rIndex)
t=rIndex(r);
result(r,:) = horzcat((x_No-y_No)./A{3}(t),(x_No-y_No))./A{4}(t),(x_No-y_No)./A{5}(t),(x_No-y_No)./A{6}(t),(x_No-y_No)./A{7}(t),(x_No-y_No)./A{8}(t));
end
I may be doing too much actually, but hopefully this helps.

how to save looping data one by one into excel file in matlab

I have a huge set of data in Excel file sheet 1. The number of columns is fixed (6) but there are lots of rows.
For every 3 rows, I need to pick out the minimum value of 2nd column and save the whole row into Excel file or sheet 2, how am I going to write the script?
item.xls (sheet 1):
0.3 0.5 0.1 0.8 0.4 0.6
0.2 0.4 0.9 0.1 0.9 0.4
0.2 0.3 0.1 0.01 0.2 0.5
0.3 0.5 0.1 0.8 0.01 0.2
0.2 0.2 0.9 0.1 0.2 0.4
0.2 0.3 0.1 0.01 0.3 0.5
.......
In the first 3 rows, the minimum value of 2nd column is 0.3, then write the whole row into sheet 2 of the Excel file.
Then the next 3 rows, the minimum value of 2nd column is 0.2, then write the whole row into sheet 2 of the Excel file.
The result I would like to get is:
item.xls (sheet2):
0.2 0.3 0.1 0.01 % 1st 3 rows, the minimum value is 0.3 in 2nd column
0.2 0.2 0.9 0.1 % 2nd set of 3 rows, the minimum value is 0.2 in 2nd column
...
I will show how to extract the relevant rows from the data in a vectorized manner. I will leave the part of reading/writing excel files to you (it should be straightforward):
%# sample data
data = rand(3*10,6);
%# for each three rows, find the min of second column, and get the row index
[r c] = size(data);
d = permute(reshape(data',[c 3 r/3]),[2 1 3]); %'# split into third dimension
[~,idx] = min(d(:,2,:)); %# find min of col2
idx = squeeze(idx) + (0:3:(r-1))'; %'# adjust indices
%# extract these rows from the data matrix
result = data(idx,:);
Down, some clarification on your problem would help to find a better solution. Based on my interpretation of your question, the following bit may help. I'm generating random test data here.
% the number of test data rows
N = 12;
% generate some random vectors for testing
test1 = rand(N,1);
test2 = rand(N,1);
test3 = rand(N,1);
test4 = rand(N,1);
% create a temporary matrix to store the minimum of every
% 3 row set
final = zeros(N/3,4);
% loop in increments of 3
j = 1;
for k=1:3:N
tmp = test2(k:k+2);
% find the index of the minimum in this 3 row group of the 2nd col
idx = find(tmp<=min(tmp));
% offset idx to index into the original data properly
idx = idx+k-1;
% assign the "row" to the final variable
final(j,:)=[test1(idx) test2(idx) test3(idx) test4(idx)];
j = j+1;
end
% write the full results out at once
xlswrite('test.xls',final);
Try this out and if it's not quite what you are looking for, post a comment to clarify your question.