How could this file be stored in matlab - matlab

I have this excel file attached, I am wondering how I could store it in matlab such that I could refrence it as A.AX, B.BY etc. What is the fastest way to do this. Or could I convert the excel file to a matlab file?

I saw that you already accepted, but here is another option
data = xlsread('Book1.xlsx');
a = data(:,1:4) ;
b = data(:,6:9) ;
c = data(:,11:14) ;
A = cell2struct( num2cell(a, 1) , {'AW', 'AX', 'AY', 'AZ'}, 2);
B = cell2struct( num2cell(b, 1) , {'BW', 'BX', 'BY', 'BZ'}, 2);
C = cell2struct( num2cell(c, 1) , {'CW', 'CX', 'CY', 'CZ'}, 2);

One way to do this is to import each column in row 3 of your doc as a matrix and then format them into tables named(A, B, C...)
For example:
AW = [148;174;177;217;280;145;291]; % Entries in column AW
AX = [376;360;553;390;464;359;411]; % Entries in column AX
A = table(AW,AX); % AW and AX are put into table named A
You can then easily acces each value or column by for example A.AW(1) or A.AW(:) etc.
The final table looks like this:

Related

How to load tables and save tables from different .mat files and create new table dimension for each file

I am using Matlab 2019 and I saved a large number of different tables with the same name, each in a .mat-file with a different name. I'd like to load them and save them in a new table together.
I need a table that has the same variables (variable1, variable2, variable3), and numbers but an additional dimension for the different .mat-files. I.e. in the dummy code below the size of the table allData should be: 2 x 3 x 2.
If I simply concatenate them like this [Results1.Inpts; Results2.Inpts], then the table is 4 x 3 and I cannot distinguish the data from the different files.
Also I have a large number of .mat-files, so I would like to automate it like done here (https://www.mathworks.com/matlabcentral/answers/233745-loading-mat-files-with-same-variable-name), which I tried to do for my table below, but it didn't work.
Please find my dummy code below.
%% Create data and .mat files
clc;
clear;
close all;
format long;
Names = {'variable1','variable2','variable3'};
Numbers1 = [2, 3, 4; 3, 4, 5];
Numbers2 = [1, 4, 10; 2, 6, 3];
Inpts = array2table(Numbers1,'VariableNames',Names);
save('Results1.mat');
clear Inpts;
Inpts = array2table(Numbers2,'VariableNames',Names);
save('Results2.mat');
clear;
%% Analyse data
files = dir('*.mat');
allData = table(size(files));
for ii=1:length(files)
aFileData = load(files(ii).name);
allData{ii} = aFileData.Inpts;
end
I think you just need to add a column in each table before concatenation
allData = cell(numel(files),1); % Store the tables in a cell
for ii=1:length(files)
aFileData = load(files(ii).name);
% Add a column
aFileData.FileName(:) = {files(ii).name};
% Stick the modified table in the cell
allData{ii} = aFileData.Inpts;
end
% Merge tables
allData = vertcat( allData{:} );
If you really want to do a 3-dimensional array with the third dimension corresponding to files, you can't use a table, because tables are inherently two-dimensional. Instead, convert your table data back to a matrix after reading it, and then concatenate them along the third dimension.
allData = cell(numel(files), 1);
for i = 1:numel(files)
fileTable = load(files(i).name);
fileMat = table2array(fileTable);
allData{i} = fileMat;
end
data = cat(3, allData{:});

How to store .csv data and calculate average value in MATLAB

Can someone help me to understand how I can save in matlab a group of .csv files, select only the columns in which I am interested and get as output a final file in which I have the average value of the y columns and standard deviation of y axes? I am not so good in matlab and so I kindly ask if someone to help me to solve this question.
Here what I tried to do till now:
clear all;
clc;
which_column = 5;
dirstats = dir('*.csv');
col3Complete=0;
col4Complete=0;
for K = 1:length(dirstats)
[num,txt,raw] = xlsread(dirstats(K).name);
col3=num(:,3);
col4=num(:,4);
col3Complete=[col3Complete;col3];
col4Complete=[col4Complete;col4];
avgVal(K)=mean(col4(:));
end
col3Complete(1)=[];
col4Complete(1)=[];
%columnavg = mean(col4Complete);
%columnstd = std(col4Complete);
% xvals = 1 : size(columnavg,1);
% plot(xvals, columnavg, 'b-', xvals, columnavg-columnstd, 'r--', xvals, columnavg+columstd, 'r--');
B = reshape(col4Complete,[5000,K]);
m=mean(B,2);
C = reshape (col4Complete,[5000,K]);
S=std(C,0,2);
Now I know that I should compute mean and stdeviation inside for loop, using mean()function, but I am not sure how I can use it.
which_column = 5;
dirstats = dir('*.csv');
col3Complete=[]; % Initialise as empty matrix
col4Complete=[];
avgVal = zeros(length(dirstats),2); % initialise as columnvector
for K = 1:length(dirstats)
[num,txt,raw] = xlsread(dirstats(K).name);
col3=num(:,3);
col4=num(:,4);
col3Complete=[col3Complete;col3];
col4Complete=[col4Complete;col4];
avgVal(K,1)=mean(col4(:)); % 1st column contains mean
avgVal(K,2)=std(col4(:)); % 2nd column contains standard deviation
end
%columnavg = mean(col4Complete);
%columnstd = std(col4Complete);
% xvals = 1 : size(columnavg,1);
% plot(xvals, columnavg, 'b-', xvals, columnavg-columnstd, 'r--', xvals, columnavg+columstd, 'r--');
B = reshape(col4Complete,[5000,K]);
meanVals=mean(B,2);
I didn't change much, just initialised your arrays as empty arrays so you do not have to delete the first entry later on and made avgVal a column vector with the mean in column 1 and the standard deviation in column 1. You can of course add two columns if you want to collect those statistics for your 3rd column in the csv as well.
As a side note: xlsread is rather heavy for reading files, since Excel is horribly inefficient. If you want to read a structured file such as a csv, it's faster to use importdata.
Create some random matrix to store in a file with header:
A = rand(1e3,5);
out = fopen('output.csv','w');
fprintf(out,['ColumnA', '\t', 'ColumnB', '\t', 'ColumnC', '\t', 'ColumnD', '\t', 'ColumnE','\n']);
fclose(out);
dlmwrite('output.csv', A, 'delimiter','\t','-append');
Load it using csvread:
data = csvread('output.csv',1);
data now contains your five columns, without any headers.

MATLAB xlswrite name data

How can I assign a name to a matrix being written from MATLAB to Excel using xlswrite?
This is equivalent to opening the xls sheet, selecting the data and right-click->define name. Here I can assign a string to the matrix. How can I do this from MATLAB?
Another application I use reads the data from the xls file based on named range.
You cannot do that from the function xlswrite as far as i know. You have to use an excel COM server from within Matlab.
The example below is derived from the Mathworks example, but adapted to your need.
Note that you won't need to use xlswrite this way, you input your data directly into the excel sheet.
%// First, open an Excel Server.
e = actxserver('Excel.Application');
%// Insert a new workbook.
eWorkbook = e.Workbooks.Add;
e.Visible = 1;
%// Make the first sheet active.
eSheets = e.ActiveWorkbook.Sheets;
eSheet1 = eSheets.get('Item', 1);
eSheet1.Activate;
%// Name the range you want:
e.Names.Add( 'TestRange' , '=Sheet1!$A$1:$B$2' ) ;
%// since you are here, directly put the MATLAB array into the range.
A = [1 2; 3 4];
eActivesheetRange = e.Activesheet.get('Range', 'TestRange');
eActivesheetRange.Value = A ;
%// Now, save the workbook.
eWorkbook.SaveAs('myfile.xls');
Edit to answer your question in comment:
If you want to programatically define the range address, you have to build the address as a string.
The row index is easy enough, but excel activeX in Matlab does not allow referencing cells/column/range by index, so there is a bit more fiddling to get the address of the column right (in case you overflow on the AAA... ranges.
The bit below should let you do that:
%// test data
A = rand(4,32);
%// input the upper left start of the range you want
sheetName = 'Sheet1' ;
startCol = 'Y' ;
startRow = 4 ;
%// calculate the end coordinates of the range
endRow = startRow + size(A,1)-1 ;
%// a bit more fiddling for the columns, as they could have many "characters"
cols = double(startCol)-64 ;
colIndex = sum(cols .* 26.^(length(cols)-1:-1:0)) ; %// index of starting column
endCol = eSheet1.Columns.Item(colIndex+size(A,2)-1).Address ;
endCol = endCol(2:strfind(endCol, ':')-1) ; %// column string reference
%// build range string in excel style
rngString = sprintf('=%s!$%s$%d:$%s$%d',sheetName,startCol,startRow,endCol,endRow) ;
myRange = eSheet1.Range(rngString) ; %// reference a range object
myRange.Value = A ; %// assign your values
%// Add the named range
e.Names.Add( 'TestRange' , myRange ) ;
The test data deliberately overflow from column Y to column BD to make sure that the address translation could handle (i) adding a character, and (ii) overflowing from Ax to By. This seems to work good, but if your data arrays are not that wide then you don't need to worry about it anyway.

How to solve the .mat file sorting?

I have three .mat files, A.mat, B.mat and C.mat. And the content of the .mat files look like this:
![enter image description here][1]
It is in r2 = [rs2,cs2,sortedValues2] format. How can I sort rs2(e.g, 3468, 3909...) of the three
.mat files together in increasing order, and count the number of appearance of each element of rs2?
Anyone can give me any suggestion?
Original
First, you're going to want load each files r2, then pull out it's rs(1, :) value into a column vector, then sort that column vector. Once you have the vector, use logical indexing to determine how many times each element repeats. Finally, attach those tow columns together to attach each element to it's corresponding count. The output vector will have duplicate rows, but I assume that won't be a problem.
allData = [load('A.mat',r2); load('B.mat',r2)l; load('C.mat',r2)];
colVector = allData(:, 1);
sortedVec = sort(colVector);
countVec = zeros(size(sortedVec));
for ii = 1:length(sortedVec)
countVec(ii) = sum(sortedVec==sortedVec(ii));
end
outputVec = [sortedVec, countVec]
Edit
Since your edited question is easy, and almost the same as your original, I'll answer it here. Most of the code is the same, you just need to get the data out of the cell array instead of the files. Like so:
colVector = [yourCellArray{:}];
sortedVec = sort(colVector);
countVec = zeros(size(sortedVec));
for ii = 1:length(sortedVec)
countVec(ii) = sum(sortedVec==sortedVec(ii));
end
outputVec = [sortedVec, countVec]
load A
rs2_1 = r2(:,1);
clearvars r2
load B
rs2_2 = r2(:,1);
clearvars r2
load C
rs2_3 = r2(:,1);
clearvars r2
% to combine
rs2_combined = [rs2_1;rs2_2;rs2_3];
% to sort
rs2_sorted = sort(rs2_combined);
% to count for appearance
rs2_count = hist(rs2_combined, min(rs2_combined):1:max(rs2_combined));
EDIT: using cell arrays
% recreate your situation
R = cell(11,10);
R = cellfun(#(x) [randi(3000,50,1),ones(50,1),ones(50,1)*-.008], R,'UniformOutput', false);
% extract rs2
r = cell2mat( reshape(R, [1,1,11,10]) );
rs2 = reshape( r(:,1,:,:), [50*11*10,1] );
% do what you want
rs2_sorted = sort(rs2);
rs2_count = hist(rs2, min(rs2):1:max(rs2));
note - I assumed you have 50x3 arrays. If merely 50x1, then reshape(R, [1,11,10]) and reshape( r, [50*11*10,1] ); also works.
hist put all numbers into different bins of different values. It's equivalent to do
rs2_scale = min(rs2_combined):1:max(rs2_combined);
rs2_count = zeros(1, length(rs2_scale));
for ii = 1:length(rs2_scale)
rs2_count(ii) = sum( rs2_combined == rs2_scale(ii) );
end
To remove zero-count numbers -
rs2_count(rs2_count==0) = [];
Then you can calculate the probability -
rs2_prob = rs2_count / sum(rs2_count);
Validate this answer by
>> sum(rs2_prob)
ans =
1.0000

MATLAB convert from struct to table and ouput as csv

As part of an image processing pipeline using 'regionprops' in Matlab I generate the struct:
vWFfeatures =
1631x1 struct array with fields:
Area
Centroid
MajorAxisLength
MinorAxisLength
Eccentricity
EquivDiameter
Where 'Centroid' is a Vector containing [x, y] for example [12.4, 26.2]. I would like to convert this struct to a table and save as a CSV file. The objective is to separate the 'Centroid' vector into two columns in the table labelled Centroid_X and Centroid_Y for example. I am not sure how to achieve this.
So far I have investigated using the 'struct2table' function. This ouputs the 'Centroid' as one column. In addition when I try to assign the output to a variable I get an error:
table = struct2table(vWFfeatures)
Error using struct2table
Too many output arguments.
I cannot understand this, any help please?
Since the original struct2table isn't available to you, you might want to implement specifically the behavior you're trying to achieve yourself.
In this case, this means extracting the values you want to save, (split the array,) then save the data:
data_Centroid = vertcat(vWFfeatures.Centroid); %// contains the centroid data
Centroid_X = data_Centroid(:,1); %// The first column is X
Centroid_Y = data_Centroid(:,2); %// the second column is Y
csvwrite('centroid.csv',data_Centroid); %// writes values into csv
If you want column headers in your csv, it gets complicated because csvwrite can only handle numeric arrays:
celldata = num2cell(num2str(data_Centroid)); %// create cell array
celldata(:,3) = celldata(:,4); %// copy col 4 (y data) into col 3 (spaces)
for i=1:length(celldata)
celldata{i,2} = ','; %// col 2 has commas
celldata{i,4} = '\n'; %// col 4 has newlines
end
celldata = celldata'; %'// transpose to make the entries come columnwise
strdata = ['Centroid_X,Centroid_Y\n',celldata{:}]; %// contains all as string
fid = fopen('centroid.csv','w'); % writing the string into the csv
fprintf(fid,strdata);
fclose(fid);
This is how I solved it in the end: extracted each field from struct used horzcat to join into a new array then defined headers and used csvwrite_with_headers, to ouput to csv.
wpbFeatures = regionprops(vWFlabelled, 'Area','Centroid', 'MajorAxisLength', 'MinorAxisLength', 'Eccentricity', 'EquivDiameter');
wpbArea = vertcat(wpbFeatures.Area);
wpbCentroid = vertcat(wpbFeatures.Centroid);
wpbCentroidX = wpbCentroid(:,1);
wpbCentroidY = wpbCentroid(:,2);
wpbFeret = max(imFeretDiameter(vWFlabelled, linspace(0,180,201)), [], 2);
wpbMajorAxisLength = vertcat(wpbFeatures.MajorAxisLength);
wpbMinorAxisLength = vertcat(wpbFeatures.MinorAxisLength);
wpbEccentricity = vertcat(wpbFeatures.Eccentricity);
wpbEquivDiameter = vertcat(wpbFeatures.EquivDiameter);
wpbFeatures = horzcat(wpbArea, wpbCentroidX, wpbCentroidY, wpbFeret, wpbMajorAxisLength, wpbMinorAxisLength, wpbEccentricity, wpbEquivDiameter);
headers = {'Area','CentroidX','CentroidY', 'Feret', 'MajorAxisLength', 'MinorAxisLength', 'Eccentricity', 'EquivDiameter'};
csvwrite_with_headers(strcat(PlateName, '_ResultsFeatures.csv'),wpbFeatures,headers);