Is it possible to use the for-loop for this purpose?

1 view (last 30 days)
Although now I'm doing this work manually by my hand if there is any chance to know I want to ask is there any way to do this using for loop?
I want to polyfit two by two based on a rule and know slope and y-intercept for each one that runs.
I have a table that describes the name of a couple of station names that should be used in polyfit together. on the other hand, I have a cell including monthly tables for these stations data.
I wonder if any way available to do this like in the code below automatically: (In the table that describes the name of couple station name that should be used in polyfit together there is Ahvaz and Ramhormoz is beside each other)
%calculate P for January (thanks to Adam Danz)
Ahvaz_Jan = getfield(finalStations,'Ahvaz_Jan');
Ramhormoz_Jan = getfield(finalStations,'Ramhormoz_Jan');
nanIdx = isnan(Ahvaz_Jan.tmax_m) | isnan(Ramhormoz_Jan.tmax_m);
P = polyfit(Ahvaz_Jan.tmax_m(~nanIdx), Ramhormoz_Jan.tmax_m(~nanIdx), 1); % January P (slope and Y intercept)
% calculate P for Feburary
Ahvaz_Feb = getfield(finalStations,'Ahvaz_Feb');
Ramhormoz_Feb = getfield(finalStations,'Ramhormoz_Feb');
nanIdx = isnan(Ahvaz_Feb.tmax_m) | isnan(Ramhormoz_Feb.tmax_m);
P = polyfit(Ahvaz_Feb.tmax_m(~nanIdx), Ramhormoz_Feb.tmax_m(~nanIdx), 1); % Feburary P (slope and Y intercept)
% For March ...
% ...For December
% looking for next two stations name from table_of_couple_stations.xlsx and do above steps for them
and then looking at the table that describes the name of a couple of station names that should be used in polyfit together and find the next couple and do this for it, and repeat this process until the end, and gives me a table of all P with corresponding stations name.
I don't know if this could be done in Matlab but if there is any way it's a fabulous moment for me.
  2 Comments
Adam Danz
Adam Danz on 27 Jan 2020
I didn't recommend using getfield.
Ahvaz_Jan = getfield(finalStations,'Ahvaz_Jan');
Ramhormoz_Jan = getfield(finalStations,'Ramhormoz_Jan');
That can be replaced by
Ahvaz_Jan = finalStations.Ahvaz_Jan; % or finalStations(1).Ahvaz_Jan
Ramhormoz_Jan = finalStations.Ramhormoz_Jan; % or finalStations(1).Ramhormoz_Jan
That's described in the first line of text in getfield().
Adam Danz
Adam Danz on 27 Jan 2020
It looks like you went with the structure approach in this question/answer.
Now you have a structure with 852 uniquely named fields, each containing a table for a station and a month. If you want to access a specific field such as the Ahvaz station for the month of January ("Ahvaz_Jan"), you'll have to construct the field name strings like this.
fieldString = sprintf('%s_%s','Ahvaz','Jan');
T = finalStations.(fieldString);
I think the cell array approach in that question/answer would be easier to work with (I'm biased because I wrote that answer). With that approach, you have a nx12 cell array of n-stations and 12 months. You also have a 1xn cell array of station names. So identifying the table would look like this.
T = Cmo{strcmp(stationList,'Ahvaz'), 1}
% Where "stationList" is your cell array of station names
% and the 1 is for January.

Sign in to comment.

Accepted Answer

Adam Danz
Adam Danz on 27 Jan 2020
Using the cell approach where Cmo is a nx12 cell array of n station-tables for 12 months.
stationList is read in as a table. The months are added to the table.
All stations listed in the excel file are located in your data except for "Qom".
See inline comments for details.
% Load data
load('C')
% Change "data" column to "date"
for i = 1:numel(C)
C{i}.Properties.VariableNames = strrep(C{1}.Properties.VariableNames,'data','date');
end
% Create the nx12 cell array of tables (n stations, 12 months)
Cmo = cell(numel(C),12);
for i = 1:numel(C)
Cmo(i,:) = arrayfun(@(m){C{i}(month(C{i}.date) == m, :)},1:12);
end
% Get station name from each row of Cmo
stationNames = cellfun(@(T)unique((T.station_name(~ismissing(T.station_name)))),Cmo(:,1));
% Get station pairs table from excel file
stationList = readtable('table_of_couple_stations.xlsx');
% select which months you want to access
months = 1:12;
% Add month columns to the stationNames table
% Each element of the month columns will be a 1x2 vector that will
% contain the linear regression coeffs.
monthNames = month(datetime(1, months, 1), 's');
newColumns = repmat({nan(height(stationList),2)},1,numel(monthNames));
stationList = [stationList, table(newColumns{:},'VariableNames', monthNames)];
% Loop through each pair in stationList
for i = 1:height(stationList)
% Locate the pairs or stations in Cmo
rowIdx1 = strcmp(stationNames, stationList.station_name{i}); % use find(rowIdx1) to see row number
rowIdx2 = strcmp(stationNames, stationList.closest_station{i}); % use find(rowIdx2) to see row number
% If station could not be located, skip this iteration and throw warning.
if ~any(rowIdx1)
warning('%s could not be located.',stationList.station_name{i})
continue
end
if ~any(rowIdx2)
warning('%s could not be located.',stationList.closest_station{i})
continue
end
% Loop through the selected months
for j = 1:numel(months)
% Extract tables for given station and month
T1 = Cmo{rowIdx1, months(j)};
T2 = Cmo{rowIdx2, months(j)};
% Remove missing values and compute linear reg coeffs.
nanIdx = isnan(T1.tmax_m) | isnan(T2.tmax_m);
stationList.(monthNames{j})(i,:) = polyfit(T1.tmax_m(~nanIdx), T2.tmax_m(~nanIdx), 1);
end
end
Look at the first few rows of the updated stationList table.
>> head(stationList)
ans =
8×14 table
station_name closest_station Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
__________________ _____________________________ ___________________ ___________________ __________________ __________________ __________________ __________________ _____________________ ____________________ __________________ ___________________ ___________________ ____________________
{'Abadan' } {'Bandar-E- Mahshahr' } 1.0029 -0.56805 0.99101 -0.3693 0.9674 0.03199 0.92499 1.8964 0.89697 3.4205 0.82895 6.7491 0.38668 27.331 0.016655 43.889 0.47415 21.034 0.66668 11.245 0.92907 1.4489 0.97751 0.032892
{'Abali' } {'Tehran (Mehrabad Airport)'} 1.101 8.0531 1.0942 9.6046 0.88167 11.602 0.8317 13.04 0.9531 12.168 0.70668 18.054 0.69229 18.706 0.7263 17.201 0.81482 13.946 0.84358 12.264 0.88557 10.139 0.91919 7.9292
{'Abumusa Island'} {'Siri Island' } 0.8699 3.0804 0.76932 5.3086 1.0443 -1.3821 0.90781 3.1134 0.69469 10.979 0.6954 10.825 0.76521 8.1086 0.6392 12.767 0.76524 8.2608 1.0202 -0.51768 0.89973 3.1358 0.8468 3.855
{'Ahar' } {'Tabriz' } 0.89695 -0.2543 0.82347 1.7484 0.82964 2.8538 0.77454 5.0873 0.7649 7.0762 0.79252 8.9474 0.83043 9.8787 0.72213 12.924 0.71801 10.897 0.62234 9.3066 0.73612 3.7588 0.8854 -0.044669
{'Ahvaz' } {'Ramhormoz' } 1.0585 -1.064 0.99794 -0.28061 1.0827 -2.6469 1.061 -2.3963 0.96587 1.2413 0.95975 1.5445 0.99822 -0.2165 0.99632 -0.20757 0.8994 3.9369 0.89535 3.6672 1.0306 -0.84648 1.0153 -0.12595
{'Anar' } {'Shahrebabak' } 0.85936 -0.978 0.93761 -2.4127 0.9901 -3.5843 1.0178 -4.3328 0.87629 0.62758 0.87015 1.6203 0.82648 3.6828 0.86516 2.1822 0.75321 5.5296 0.73567 4.7125 0.69743 3.6285 0.90427 -1.0359
{'Arak' } {'Qom' } NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
{'Babolsar' } {'Nowshahr' } 1.0055 -0.92578 1.0112 -1.1519 0.88316 0.23299 1.0007 -1.699 1.0348 -2.5691 0.99892 -1.713 0.9417 0.00020517 0.9914 -1.4848 1.0085 -2.026 0.98938 -1.0535 0.9681 -0.34382 1.0042 -0.58969
To access the coefficients for Ahar-Tabriz & February,
rowIdx = strcmp(stationList.station_name,'Ahar') & strcmp(stationList.closest_station,'Tabriz');
coeffs = stationList.Feb(rowIdx,:);
  2 Comments
BN
BN on 27 Jan 2020
Thank you so much. It's perfect, clear, and precise, I really appreciate your time and attention.
Best Regards and Best Wishes.

Sign in to comment.

More Answers (1)

Mohammad Sami
Mohammad Sami on 27 Jan 2020
Edited: Mohammad Sami on 27 Jan 2020
You can use the for loop. Modify it as you deem fit.
% load from xlsx or from your mat file.
matching_station = readtable('table_of_couple_stations.xlsx');
monthnames = {'Jan' 'Feb' 'Mar' 'Apr'} % and the rest of names
for i = 1:height(matching_station);
for j = 1:length(monthnames)
nameA = [matching_station.station_name{i} '_' monthnames{j}]; % {i} assumed its a cell array
nameB = [matching_station.closest_station{i} '_' monthnames{j}];
tempA = getfield(finalStations,nameA);
tempB = getfield(finalStations,nameB);
nanIdx = isnan(tempA.tmax_m) | isnan(tempB.tmax_m);
P = polyfit(tempA.tmax_m(~nanIdx), tempB.tmax_m(~nanIdx), 1);
end
end
  3 Comments
BN
BN on 27 Jan 2020
Dear Adam Danz, You are right the structure approach in this question/answer does not match some of the field names. I was picked this approach because I thought thanks to the abbreviation of month name in front of station names, it would be easy to use in the loop.
May I ask you if you please guide me on how to use the cell approach in this problem?
Thank you
BN
BN on 27 Jan 2020
Edited: BN on 27 Jan 2020
Here I can manually calculate polyfit for stations based on each month using cell array approach.
Cmo = cell(numel(C),12);
for i = 1:numel(C)
Cmo(i,:) = arrayfun(@(m){C{i}(month(C{i}.date) == m, :)},1:12);
end
stationList = readtable('table_of_couple_stations.xlsx');
stationList = table2cell(stationList);
Ahvaz_jan = Cmo{strcmp(stationList,'Ahvaz'), 1};
Ramhormoz_jan = Cmo{strcmp(stationList,'Ramhormoz'), 1};
%remove pairs of data that contain a NaN value
nanIdx = isnan(Ahvaz_jan.tmax_m) | isnan(Ramhormoz_jan.tmax_m);
P = polyfit(Ahvaz_jan.tmax_m(~nanIdx), Ramhormoz_jan.tmax_m(~nanIdx), 1);
But still, I think about how to write the loop-for in order to make it automatically run for each one.
Thanks

Sign in to comment.

Categories

Find more on Data Type Identification in Help Center and File Exchange

Tags

Products


Release

R2018b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!