Append values from textscan into cell array literately in a loop - matlab

Currently I have a txt file with data as shown below:
A11
Temperature=20 Weight=120 Speed=65
B13
Temperature=21 Weight=121 Speed=63
F24
Temperature=18 Weight=117 Speed=78
D43
Temperature=16 Weight=151 Speed=42
C32
Temperature=15 Weight=101 Speed=51
I would like to read the value into a cell array and convert it as matrix.
Below is my code:
% At first I read the data into a 1 column array
fid=fopen('file.txt');
tline = fgetl(fid);
tlines = cell(0,1);
while ischar(tline)
tlines{end+1,1} = tline;
tline = fgetl(fid);
end
fclose(fid);
% Then I check the size of the cell array
CellSize = size(tlines);
DataSize = CellSize(1,1);
% At last I setup a loop and literately read and input the values
Data = cell(0,3);
for i = 1:DataSize
Data{end+1,3} = textscan(tlines{i,1},'Temperature=%f Weight=%f Speed=%f');
end
However, I got 10x3 empty cell array.
[] [] *1x3cell*
[] [] *1x3cell*
[] [] *1x3cell*
[] [] *1x3cell*
[] [] *1x3cell*
[] [] *1x3cell*
[] [] *1x3cell*
[] [] *1x3cell*
[] [] *1x3cell*
[] [] *1x3cell*
I know the problem comes from the input of textscan value into the cell array. Can you help me fix the problem? Also how can I toss the empty value if the data doesn't contain the specific format.

The only mistake you made, was to index the content of Data using {}, and not the cells using (), see the help.
I modified the last part of your script:
% At last I setup a loop and literately read and input the values
Data = cell(DataSize, 3);
for i = 1:DataSize
Data(i, :) = textscan(tlines{i}, 'Temperature=%f Weight=%f Speed=%f')
end
Gives the following output:
Data =
{
[1,1] = [](0x1)
[2,1] = 20
[3,1] = [](0x1)
[4,1] = 21
[5,1] = [](0x1)
[6,1] = 18
[7,1] = [](0x1)
[8,1] = 16
[9,1] = [](0x1)
[10,1] = 15
[1,2] = [](0x1)
[2,2] = 120
[3,2] = [](0x1)
[4,2] = 121
[5,2] = [](0x1)
[6,2] = 117
[7,2] = [](0x1)
[8,2] = 151
[9,2] = [](0x1)
[10,2] = 101
[1,3] = [](0x1)
[2,3] = 65
[3,3] = [](0x1)
[4,3] = 63
[5,3] = [](0x1)
[6,3] = 78
[7,3] = [](0x1)
[8,3] = 42
[9,3] = [](0x1)
[10,3] = 51
}
Afterwards you could do:
% Clean up.
for i = DataSize:-1:1
if (isempty([Data{i, :}]))
Data(i, :) = [];
end
end
So that your output looks like this:
Data =
{
[1,1] = 20
[2,1] = 21
[3,1] = 18
[4,1] = 16
[5,1] = 15
[1,2] = 120
[2,2] = 121
[3,2] = 117
[4,2] = 151
[5,2] = 101
[1,3] = 65
[2,3] = 63
[3,3] = 78
[4,3] = 42
[5,3] = 51
}
Also, please don't do things like Data{end+1,3}, if the size is known in advance. I also modified this accordingly.

If you want to keep the header/name, this is not terribly elegant, but it will work:
fin = 'yourfilename.txt';
fid = fopen(fin);
stuff = textscan(fid, '%s');
fclose(fid);
stuff = stuff{:};
stuff = strrep(stuff, 'Temperature=', '');
stuff = strrep(stuff, 'Weight=', '');
stuff = strrep(stuff, 'Speed=', '');
len = length(stuff) / 4;
name = cell(1,len);
temp = NaN(1,len);
wt = NaN(1,len);
speed = NaN(1,len);
counter = 0;
for ii = 1:len
name(ii) = stuff(ii + counter);
temp(ii) = str2double(stuff(ii + counter +1));
wt(ii) = str2double(stuff(ii + counter +2));
speed(ii) = str2double(stuff(ii + counter +3));
counter = counter + 3;
end
name = cell2table(name', 'VariableNames', {'Name'});
temp = array2table(temp', 'VariableNames', {'Temperture'});
wt = array2table(wt', 'VariableNames', {'Weight'});
speed = array2table(speed', 'VariableNames', {'Speed'});
data = [name temp wt speed];

Related

how to select specific columns or rows of a table in appdesigner of matlab?

I Want to select a row or column of a table with the edit field component and do some actions on these data and show the result in the first cell of table ([1,1])
rowNames={1:100}
columnName={A:ZZ}
like this:
sum(A1:A20) or Max(AA5:AA10)
I want to write above order in the edit field component
and show the result of them in cell[A,1]
How can I do that?
Here's an implementation that might be similar to what you are attempting to achieve.
Any subset can be calculated using the command such as: Sum(A1:A2)U(B2:B3)
Where A indicates the columns apart of the set and B indicates the rows apart of the set.
Some more test functions include:
Sum(A1:A4) and
Sum(B1:B4)
%Random data%
global Data;
Data = [1 2 3 4; 1 2 3 4; 1 2 3 4; 1 2 3 4; 1 2 3 4];
%Converting data into table%
Data = array2table(Data);
%Grabbing the size of the data%
[Number_Of_Rows, Number_Of_Columns] = size(Data);
%Creating arrays for setting the row and column names%
Row_Labels = strings(1,Number_Of_Rows);
Column_Labels = strings(1,Number_Of_Columns);
for Row_Scanner = 1: +1: Number_Of_Rows
Row_Labels(1,Row_Scanner) = ["B" + num2str(Row_Scanner)];
end
for Column_Scanner = 1: +1: Number_Of_Columns
Column_Labels(1,Column_Scanner) = ["A" + num2str(Column_Scanner)];
end
Row_Labels = cellstr(Row_Labels);
Column_Labels = cellstr(Column_Labels);
%UItable%
Main_Figure = uifigure;
Table = uitable(Main_Figure,'Data',Data);
Table.ColumnName = Column_Labels;
Table.RowName = Row_Labels;
set(Table,'ColumnEditable',true(1,Number_Of_Columns))
%Callback function to update the table%
% Table.CellEditCallback = #(Table,event) Update_Table_Data(Table);
%UIeditfield%
Selection_Field = uieditfield(Main_Figure,'text');
Field_Height = 20;
Field_Width = 100;
X_Position = 350;
Y_Position = 200;
Selection_Field.Position = [X_Position Y_Position Field_Width Field_Height];
Result_Label = uilabel(Main_Figure);
Result_Label.Position = [X_Position Y_Position-100 Field_Width Field_Height];
Selection_Field.ValueChangedFcn = #(Selection_Field,event) Compute_Value(Table,Selection_Field,Result_Label);
%Computing value
function [Data] = Compute_Value(Table,Selection_Field,Result_Label)
Data = Table.Data;
User_Input_Function = string(Selection_Field.Value);
Function = extractBefore(User_Input_Function,"(");
% fprintf("Function: %s \n",Function);
Key_Pairs = extractBetween(User_Input_Function,"(",")");
% fprintf("Key Pairs: (%s)\n", Key_Pairs);
Key_1 = extractBefore(Key_Pairs(1,1),":");
Key_2 = extractAfter(Key_Pairs(1,1),":");
Key_1
Key_2
if length(Key_Pairs) == 2
Key_3 = extractBefore(Key_Pairs(2,1),":");
Key_4 = extractAfter(Key_Pairs(2,1),":");
Key_3
Key_4
end
%Exracting the letters of each key
if contains(Key_1, "A") == 1
% fprintf("Function on columns\n")
Minimum_Column = str2num(extractAfter(Key_1,"A"));
Maximum_Column = str2num(extractAfter(Key_2,"A"));
Table_Subset = Data(1,Minimum_Column:Maximum_Column);
end
if contains(Key_1, "B") == 1
% fprintf("Function on rows\n")
Minimum_Row = str2num(extractAfter(Key_1,"B"));
Maximum_Row = str2num(extractAfter(Key_2,"B"));
Table_Subset = Data(Minimum_Row:Maximum_Row,1);
end
if length(Key_Pairs) == 2
Minimum_Column = str2num(extractAfter(Key_1,"A"));
Maximum_Column = str2num(extractAfter(Key_2,"A"));
Minimum_Row = str2num(extractAfter(Key_3,"B"));
Maximum_Row = str2num(extractAfter(Key_4,"B"));
Table_Subset = Data(Minimum_Row:Maximum_Row,Minimum_Column:Maximum_Column);
end
Table_Subset = table2array(Table_Subset);
%Statements for each function%
if (Function == 'Sum' || Function == 'sum')
fprintf("Computing sum\n");
Result_Sum = sum(Table_Subset,'all');
Result_Sum
Result_Label.Text = "Result: " + num2str(Result_Sum);
end
if (Function == 'Max' || Function == 'max')
fprintf("Computing maximum\n");
Result_Max = max(Table_Subset);
Result_Max
Result_Label.Text = "Result: " + num2str(Result_Max);
end
if (Function == 'Min' || Function == 'min')
fprintf("Computing minimum\n");
Result_Min = min(Table_Subset);
Result_Min
Result_Label.Text = "Result: " + num2str(Result_Min);
end
end

compare more than 2 proportions matlab

Having 4 groups (A,B,C,D)
each of them containing a different number of male and female
male_A = 46
male_B = 241
male_C = 202
male_D = 113
female_A = 43
female_B = 134
female_C = 100
female_D = 53
How can I identify the groups that have a statistically different proportion of male and female? Suggestion using MATLAB would be appreciated...
POSSIBLE SOLUTION (PLEASE CHECK)
% 1st row: male
% 2nd row: female
cont = [46 241 202 113;
43 134 100 53]
mychi(cont)
%this function should calculate the Chi2
function mychi(cont)
cont = [cont, sum(cont,2)];
cont = [cont; sum(cont,1)];
counter = 1;
for i = 1 : size(cont,1)-1
for j = 1 : size(cont,2)-1
Observed(counter) = cont(i,j);
Expected(counter) = cont(i,end)*cont(end,j)/cont(end:end);
O_E_2(counter) = (abs(Observed(counter)-Expected(counter)).^2)/Expected(counter);
counter = counter + 1;
end
end
DOF = (size(cont,1)-2)*(size(cont,2)-2)
CHI = sum(O_E_2)
end
The CHI returned should be compared with the one for p<0.05 that can be found here
In my case
DOF =
3
CHI =
8.0746
CHI is > 0.352 so the groups have a biased number of male and female...
Not sure what comparison you are looking for, but the ratios can be obtained by
p = 0.05;
ratio_A = male_A ./ (male_A + female_A);
ratio_B = male_B ./ (male_B + female_B);
ratio_C = male_C ./ (male_C + female_C);
ratio_D = male_D ./ (male_D + female_D);
%Once you have ratios, you can perform analysis as mentioned on
%http://au.mathworks.com/help/stats/hypothesis-testing.html
Hope this helps
I suggest to arrange your data in a matrix and use the proper indexing according to your pourposes. Here you have an example:
male_A = 46;
male_B = 241;
male_C = 202;
male_D = 113;
female_A = 43;
female_B = 134;
female_C = 100;
female_D = 53;
matrix = [male_A female_A;
male_B female_B;
male_C female_C;
male_D female_D];
groups = ['A', 'B', 'C', 'D'];
total = (matrix(:,1)+matrix(:,2));
male_percentage = matrix(:,1)./total*100
female_percentage = matrix(:,2)./total*100
threshold = 65; %// Example threshold 65%
male_above_threshold = groups(male_percentage>threshold)
female_above_threshold = groups(female_percentage>threshold)
maximum_male_ratio = groups(male_percentage==max(male_percentage))
maximum_female_ratio = groups(female_percentage==max(female_percentage))
In your example you would get:
male_percentage =
51.6854
64.2667
66.8874
68.0723
female_percentage =
48.3146
35.7333
33.1126
31.9277
male_above_threshold =
CD
female_above_threshold =
Empty string: 1-by-0
maximum_male_ratio =
D
maximum_female_ratio =
A
Finding out the groups that are statistically different is another problem. You should provide more information in order to do that.

3-D interpolation using griddata

I have a problem for the interpolation of a 3-D array using griddata command in MATLAB. I have tried different ways but unfortunately I couldn't have handled it. The array which should be interpolated is a 182x125x35 array (longitude, latitude and depth) which is model output and I want to interpolate it on the observation data points. Thanks for the time you spend for helping me.
clear;
clc;
% Observation Data
t_obs = ncread('/disk1/Observation/data_from_data.nc','date_time');
lat_obs = ncread('/disk1/Observation/data_from_data.nc','latitude');
long_obs = ncread('/disk1/Observation/data_from_data.nc','longitude');
depth_obs = ncread('/disk1/Observation/data_from_data.nc','var1');
temp_obs = ncread('/disk1/Observation/data_from_data.nc','var2');
% Model Data
lat_m = ncread('/disk1/.../a.nc','GLat');
lon_m = ncread('/disk1/.../a.nc','GLong');
H = ncread('/disk1/.../a.nc', 'H');
sigma = ncread('/disk1/.../a.nc','SIGMAZZ');
dom = ncread('/disk1/.../a.nc','DOM');
% Rearrangement of date string to number for observation time
toffset1 = datenum([1990 01 01 00 00 00]) + datenum([0000 00 00 00 00 00]);
t = t_obs - 1;
time_obs = toffset1 + t;
% Selection of model file and date
t_mod1 = input('[yyyy mm dd] = ');
t_mod2 = input('[yyyy mm dd] = ');
toffset = datenum([1990 01 01 00 00 00]) + datenum([0000 00 00 00 00 00]);
t_mod3 = t_mod1+(0.00000001);
t_mod4 = t_mod2+(0.00000001);
date1 = datenum(t_mod3);
date2 = datenum(t_mod4);
tind_m1 = date1;
tind_m2 = date2;
time_mod = [tind_m1:tind_m2]';
ind1 = zeros(16887,1);
ind2 = zeros(16887,1);
for i = 1:16887
d = sort(abs(time_mod - time_obs(i)));
ind1(i) = find(abs(time_mod - time_obs(i)) == d(1));
ind2(i) = find(abs(time_mod - time_obs(i)) == d(2));
end
% Find temporal point of parameter for temporal interpolation
for i = 1:16887
d = sort(abs(time_mod - time_obs(i)));
ind1(i) = find(abs(time_mod - time_obs(i)) == d(1));
ind2(i) = find(abs(time_mod - time_obs(i)) == d(2));
end
% Temporal and spatial interpolation and writing the output in a .nc file
c = 1;
for n = ind1(1):ind1(16887)
for m = ind2(1):ind2(16887)
for l = 1:16887
str1 = sprintf('%4.4d',n);
str2 = sprintf('%4.4d',m);
sfile1 = (['/media/.../restart.',str1,'.nc']);
sfile2 = (['/media/.../restart.',str2,'.nc']);
temp1 = ncread(sfile1,'t',[1 1 1], [182, 125, 35]);
temp2 = ncread(sfile2,'t',[1 1 1], [182, 125, 35]);
temp_new = temp1 + ((temp2 - temp1)/(m-n))*(t(l) - n);
temp_new = griddata(lon_m,lat_m,depth_m,temp_new,long_o,lat_o,depth_obs);
c = n;
str = sprintf('%4.4d', c);
ncid = netcdf.create(['/disk1/.../tempinter/restartint.',str,'.nc'],'NC_WRITE');
x = 1:182;
y = 1:125;
z = 1:35;
dimid1 = netcdf.defDim(ncid,'xdim',length(x));
dimid2 = netcdf.defDim(ncid,'ydim',length(y));
dimid3 = netcdf.defDim(ncid,'zdim',length(z));
varidt = netcdf.defVar(ncid,'temp_new','double',[dimid1 dimid2 dimid3]);
netcdf.endDef(ncid)
netcdf.putVar(ncid,varidt,temp_new);
netcdf.close(ncid);
c = c+1;
end
end
end

How can I display different types of output in a matix in matlab?

please consider that I have different types of output in each iteration , how I can show all of them in a matrix?or in a table ? I need to have label for each column and to be accessible when I need it for calling or comparing or etc ...
for example outputs of iterations:
myfilename =
file35.txt
a_Count =
3
PPS_Count =
16
PPP_Count =
8
emo =
'trust'
x =
1
for example outputs of iteration 2:
myfilename =
file36.txt
a_Count =
5
PPS_Count =
10
PPP_Count =
8
emo =
'anger'
x =
0
for example outputs of iteration 3:
myfilename =
file37.txt
a_Count =
6
PPS_Count =
32
PPP_Count =
8
emo =
'trust'
x =
0
thanks in advance.
Here is a tutorial on creating a struct array and documentation for struct.
In your case what I would do is first create the empty struct and then loop through the files:
data_struct = struct('a_Count',{},'PPS_Count',{},'PPP_Count',{},'emo',{},'x',{});
numfiles = 1; % just for testing purposes
for findex = 1:numfiles
% Code to read in file data goes here. Replace from here to next comment.
new_a_Count = 3;
new_PPS_Count = 16;
new_PPP_Count = 8;
new_emo = 'trust';
new_x = 1;
% Replace down to here populating variables:
% new_a_Count, new_PPS_Count, new_PPP_Count, new_emo, new_x
data_struct(findex).a_Count = new_a_Count;
data_struct(findex).PPS_Count = new_PPS_Count;
data_struct(findex).PPP_Count = new_PPP_Count;
data_struct(findex).emo = new_emo;
data_struct(findex).x = new_x;
end;
% display all values in data_struct(1):
disp("data_struct(1) = ");
disp(data_struct(1));
disp("\n");
% display just the first field "a_Count"
disp("data_struct(1).a_Count = ");
disp(data_struct(1).a_Count);
Note that you can call those new variables anything, including the same names as the struct fields. Here's the output you should get when you run this:
data_struct (1) =
{
PPP_Count = 8
PPS_Count = 16
a_Count = 3
emo = trust
x = 1
}
data_struct(1).a_Count =
3

how can i reduce the following code by using any loop

num2 = xlsread('CANCER.xls','C2:C102')
[IDX,C1] = kmeans(num2,2)
num3 = xlsread('CANCER.xls','C103:C203')
[IDX,C2] = kmeans(num3,2)
num4 = xlsread('CANCER.xls','C304:C404')
[IDX,C3] = kmeans(num4,2)
num5 = xlsread('CANCER.xls','C405:C505')
[IDX,C4] = kmeans(num5,2)
num6 = xlsread('CANCER.xls','C506:C606')
[IDX,C5] = kmeans(num6,2)
num7 = xlsread('CANCER.xls','C607:C707')
[IDX,C6] = kmeans(num7,2)
num8 = xlsread('CANCER.xls','C708:C808')
[IDX,C7] = kmeans(num8,2)
num9 = xlsread('CANCER.xls','C809:C909')
[IDX,C8] = kmeans(num9,2)
num10 = xlsread('CANCER.xls','C1000:C1099')
[IDX,C9] = kmeans(num10,2)
num11= xlsread('CANCER.xls','C1100:C1199')
[IDX,C10] = kmeans(num11,2)
num12= xlsread('CANCER.xls','C1200:C1299')
[IDX,C11] = kmeans(num12,2)
num13= xlsread('CANCER.xls','C1300:C1399')
[IDX,C12] = kmeans(num13,2)
num14= xlsread('CANCER.xls','C1400:C1499')
[IDX,C13] = kmeans(num14,2)
kmns=[C1;C2;C3;C4;C5;C6;C7;C8;C9;C10;C11;C12;C13;C14]
Try this -
%%// Start and stop row numbers
start_ind = [2 103 304 405 506 607 708 809 1000 :100: 1400];
stop_ind = [start_ind(1:8)+100 start_ind(9:end) + 99];
data = xlsread('CANCER.xls'); %%// Read data in one-go
C = zeros(2,numel(start_ind)); %%// Place holder for C values
for k1 = 1:numel(start_ind)
num = data(start_ind(k1):stop_ind(k1),3); %%// Data for the specified range
[IDX,C(:,k1)] = kmeans(num,2); %%// Do the calculations
end
kmns = reshape(C,[],1); %%// Final result