How do I remove leap year data?

6 views (last 30 days)
The code works. However, I need to run eliminate all leap year data (February 29th) because March 1st and February 29th are getting mixed up in the outgoing text file. How can I do this? I have tried using braces around idxMn,2 and etc but received an error stating it's unable to use them. I also can't use leapyear for I do not have aerospace toolbox. Any help will be grateful.
close all;
clear all;
clc;
Datafiles = fileDatastore("temp_summary*.txt","ReadFcn",@readMonth,"UniformRead",true);
dataAll = readall(Datafiles)
dataAll.Year = year(dataAll.Day);
dataAll.Month = month(dataAll.Day);
dataAll.DD = day(dataAll.Day)
% Unstack variables
minT_tbl = unstack(dataAll,"MinT","Year","GroupingVariables", ["Month","DD"],"VariableNamingRule","preserve")
maxT_tbl = unstack(dataAll,"MaxT","Year","GroupingVariables", ["Month","DD"],"VariableNamingRule","preserve")
yrs =str2double(minT_tbl.Properties.VariableNames(3:end))';
% find min
[Tmin,idxMn] = min(minT_tbl{:,3:end},[],2,'omitnan');
Tmin_yr = yrs(eomday(idxMn,2),[]);
% find max
[Tmax,idxMx] = max(maxT_tbl{:,3:end},[],2,'omitnan');
Tmax_yr = yrs(eomday(idxMx,2),[]);
% find low high
[lowTMax,idxMx] = min(maxT_tbl{:,3:end},[],2,'omitnan');
LowTMax_yr = yrs(eomday(idxMx,2),[]);
% find high low
[highlowTMn,idxMn] = max(minT_tbl{:,3:end},[],2,'omitnan');
HighLowT_yr = yrs(eomday(idxMn,2),[]);
% find avg high
AvgTMx = round(mean(table2array(maxT_tbl(:,3:end)),2,'omitnan'));
% find avg low
AvgTMn = round(mean(table2array(minT_tbl(:,3:end)),2,'omitnan'));
% Results
tempTbl = [maxT_tbl(:,["Month","DD"]), table(Tmax,Tmax_yr,AvgTMx,lowTMax,LowTMax_yr,Tmin,Tmin_yr,AvgTMn,highlowTMn,HighLowT_yr)]
tempTbl2 = splitvars(tempTbl)
FID = fopen('Meda 05 Temperature Climatology.txt','w');
report_date = datetime('now','format','yyyy-MM-dd HH:MM');
fprintf(FID,'Meda 05 Temperature Climatology at %s \n', report_date);
fprintf(FID,"Month DD Temp Max (°F) Tmax_yr AvgTMax (°F) lowTMax (°F) LowTMax_yr TempMin (°F) TMin_yr AvgTMin (°F) HighlowTMin (°F) HighlowT_yr \n");
fprintf(FID,'%3d %6d %7d %14d %11d %11d %15d %11d %13d %10d %13d %17d \n', tempTbl2{:,1:end}');
fclose(FID);
winopen('Meda 05 Temperature Climatology.txt')
function Tbl = readMonth(filename)
opts = detectImportOptions(filename)
opts.ConsecutiveDelimitersRule = 'join';
opts.MissingRule = 'omitvar';
opts = setvartype(opts,'double');
opts.VariableNames = ["Day","MaxT","MinT","AvgT"];
Tbl = readtable(filename,opts);
Tbl = standardizeMissing(Tbl,{999,'N/A'},"DataVariables",{'MaxT','MinT','AvgT'})
Tbl = standardizeMissing(Tbl,{-99,'N/A'},"DataVariables",{'MaxT','MinT','AvgT'})
[~,basename] = fileparts(filename);
nameparts = regexp(basename, '\.', 'split');
dateparts = regexp(nameparts{end}, '_','split');
year_str = dateparts{end}
d = str2double(extract(filename,digitsPattern));
Tbl.Day = datetime(d(3),d(2),Tbl.Day)
end
  1 Comment
Cris LaPierre
Cris LaPierre on 8 Feb 2024
This question is getting spread across several questions, so bringing my comments here.
You need to check if the month ends in 29 before you convert Day into a datetime. That conversion happens in readMonth. Since 2/29 gets convereted to 3/1 in non-leap year years, you need to identify this date before the converstion to datetime.
Normally this wouldn't be an issue, but for some reason your files contain data for Feb 29 even in non-leap year years.
dataAll = readtable('temp_summary.05.02_1981.txt',...
"ConsecutiveDelimitersRule","join","ReadVariableNames",false,...
"Delimiter",{' ','\t','*','#'},"LeadingDelimitersRule",'ignore',...
'EmptyLineRule','skip');
dataAll.Properties.VariableNames = {'Day' 'MaxT' 'MinT' 'AvgT'};
dataAll.Day = datetime(1981,2,dataAll.Day); % 1981, which is a non-leap year
dataAll.Month = month(dataAll.Day);
dataAll.DD = day(dataAll.Day);
tail(dataAll)
Day MaxT MinT AvgT Month DD ___________ ____ ____ ____ _____ __ 22-Feb-1981 69 30 49.5 2 22 23-Feb-1981 71 20 45.5 2 23 24-Feb-1981 70 30 50 2 24 25-Feb-1981 59 31 45 2 25 26-Feb-1981 51 23 37 2 26 27-Feb-1981 61 18 38.5 2 27 28-Feb-1981 64 21 41.5 2 28 01-Mar-1981 55 40 47.5 3 1
% Remove all Feb 29 dates from the table
LY = (dataAll.Month(:)== 2 & dataAll.DD(:) == 29);
dataAll(LY,:) = [ ];
tail(dataAll)
Day MaxT MinT AvgT Month DD ___________ ____ ____ ____ _____ __ 22-Feb-1981 69 30 49.5 2 22 23-Feb-1981 71 20 45.5 2 23 24-Feb-1981 70 30 50 2 24 25-Feb-1981 59 31 45 2 25 26-Feb-1981 51 23 37 2 26 27-Feb-1981 61 18 38.5 2 27 28-Feb-1981 64 21 41.5 2 28 01-Mar-1981 55 40 47.5 3 1
As you can see, the current LY code did not remove the data. This is because 2/29 is converted to 3/1 by datetime. You need to perform your LY correction before you convert to datetime.
dataAll2 = readtable('temp_summary.05.02_1981.txt',...
"ConsecutiveDelimitersRule","join","ReadVariableNames",false,...
"Delimiter",{' ','\t','*','#'},"LeadingDelimitersRule",'ignore',...
'EmptyLineRule','skip');
dataAll2.Properties.VariableNames = {'Day' 'MaxT' 'MinT' 'AvgT'};
tail(dataAll2)
Day MaxT MinT AvgT ___ ____ ____ ____ 22 69 30 49.5 23 71 20 45.5 24 70 30 50 25 59 31 45 26 51 23 37 27 61 18 38.5 28 64 21 41.5 29 55 40 47.5
% If the last date of the imported month is 29, delete
if dataAll2.Day(end==29)
dataAll2(end,:)=[];
end
% Now you can convert Day to datetime
dataAll2.Day = datetime(1981,2,dataAll2.Day); % 1981, which is a non-leap year
dataAll2.Month = month(dataAll2.Day);
dataAll2.DD = day(dataAll2.Day);
tail(dataAll2)
Day MaxT MinT AvgT Month DD ___________ ____ ____ ____ _____ __ 21-Feb-1981 60 31 45.5 2 21 22-Feb-1981 69 30 49.5 2 22 23-Feb-1981 71 20 45.5 2 23 24-Feb-1981 70 30 50 2 24 25-Feb-1981 59 31 45 2 25 26-Feb-1981 51 23 37 2 26 27-Feb-1981 61 18 38.5 2 27 28-Feb-1981 64 21 41.5 2 28
Now there is no 3/1 data in the Feb 1981 table
Since you are using a datastore to load you files, you must make this edit in your read function.

Sign in to comment.

Accepted Answer

Star Strider
Star Strider on 5 Feb 2024
I ran your code with the provided data (here, online), however I do not see any leap year days.
That aside, something like this could work —
DateTime = datetime(2024,02,25) + caldays(0:11).'
DateTime = 12×1 datetime array
25-Feb-2024 26-Feb-2024 27-Feb-2024 28-Feb-2024 29-Feb-2024 01-Mar-2024 02-Mar-2024 03-Mar-2024 04-Mar-2024 05-Mar-2024 06-Mar-2024 07-Mar-2024
DateTime(month(DateTime) == 2 & day(DateTime) == 29) = []
DateTime = 11×1 datetime array
25-Feb-2024 26-Feb-2024 27-Feb-2024 28-Feb-2024 01-Mar-2024 02-Mar-2024 03-Mar-2024 04-Mar-2024 05-Mar-2024 06-Mar-2024 07-Mar-2024
This year happens to be a leap year, however this approach is not sensitive to the year, since it just searches for and eliminates every February 29 entry.
.
  16 Comments
Star Strider
Star Strider on 8 Feb 2024
As always, my pleasure!
Star Strider
Star Strider on 8 Feb 2024
I saw your other question and decided to see if I could incorporate an answer to it in my code.
Without changing my original code too much, I was able to recover the variable names and elimiinate the '*' and '#' characters. I also changed it to delete 29 Feb from only the non-leap years.
The code —
files = dir('*.txt');
for k = 1:numel(files)
filename = files(k).name
Tx = fileread(files(k).name);
VN = regexp(Tx(1,:), '(\s\s)|(\s\s\s)', 'split');
VN = cellfun(@strtrim,VN(2:5), 'Unif',0);
opts = detectImportOptions(files(1).name);
opts = setvartype(opts,{'Var2','Var3','Var4'},'char');
T{k,:} = readtable(filename, opts);
LLv1 = any(ismember(T{k}{:,4},{'*'}),2);
T{k}{LLv1,4} = {num2str(T{k}{LLv1,5},'%.1f')};
LLv2 = any(ismember(T{k}{:,3},{'#'}),2);
T{k}{LLv2,3:4} = [T{k}{LLv2,4},{num2str(T{k}{LLv2,5},'%.1f')}];
T{k} = T{k}(:,1:end-1);
T{k}.Properties.VariableNames = VN;
T{k}{:,2:4} = cellfun(@str2double,T{k}{:,2:4}, 'Unif',0);
Te = array2table([T{k}{:,1} cell2mat(T{k}{:,2:4})], 'VariableNames',VN);
T{k} = Te;
% T{k}
fn{k,:} = filename;
nrows = size(T{k},1);
Nr = regexp(filename,'\d*','match');
% Check = eomday(cellfun(@str2double,Nr(3)),2) % Check 'filename' Year For Leap Year
% Nr{3} = '2024'; % Artificially Assign Leap Year To Test Code
Yr = cellfun(@str2double,repmat(Nr(3),nrows,1));
Mo = cellfun(@str2double,repmat(Nr(2),nrows,1));
% T{k}.DateTime = datetime(Yr,Mo,T{k}{:,1});
T{k}.YMD = [Yr Mo T{k}{:,1}]; % Create Variable To Replace ''datetime'
end
filename = 'temp_summary.05.02_1981.txt'
filename = 'temp_summary.05.02_1982.txt'
filename = 'temp_summary.05.02_2016.txt'
filename = 'temp_summary.05.03_1981.txt'
filename = 'temp_summary.05.03_1982.txt'
filename = 'temp_summary.05.03_2016.txt'
T{:}
ans = 29x5 table
Day Maximum Temp Minimum Temp Average Temp YMD ___ ____________ ____________ ____________ ____________________ 1 57 12 34.5 1981 2 1 2 58 19 38.5 1981 2 2 3 59 17 37 1981 2 3 4 59 12 35.5 1981 2 4 5 50 12 31.5 1981 2 5 6 54 31 42.5 1981 2 6 7 60 13 36.5 1981 2 7 8 51 29 40 1981 2 8 9 52 36 44 1981 2 9 10 59 24 41.5 1981 2 10 11 61 36 48.5 1981 2 11 12 67 28 46.5 1981 2 12 13 63 21 42 1981 2 13 14 63 29 46 1981 2 14 15 70 26 47 1981 2 15 16 72 29 51.5 1981 2 16
ans = 29x5 table
Day Maximum Temp Minimum Temp Average Temp YMD ___ ____________ ____________ ____________ ____________________ 1 51 32 42.5 1982 2 1 2 52 24 39 1982 2 2 3 59 23 40 1982 2 3 4 45 27 37 1982 2 4 5 41 16 28.5 1982 2 5 6 48 10 28 1982 2 6 7 48 8 27 1982 2 7 8 52 20 36 1982 2 8 9 50 19 33.5 1982 2 9 10 35 30 33.5 1982 2 10 11 54 31 42.5 1982 2 11 12 56 27 40.5 1982 2 12 13 60 27 43.5 1982 2 13 14 63 35 48 1982 2 14 15 66 31 47.5 1982 2 15 16 70 40 56 1982 2 16
ans = 29x5 table
Day Maximum Temp Minimum Temp Average Temp YMD ___ ____________ ____________ ____________ ____________________ 1 40 27 35.6 2016 2 1 2 40 20 29.1 2016 2 2 3 44 18 29.9 2016 2 3 4 50 22 35.6 2016 2 4 5 55 22 37.8 2016 2 5 6 59 22 39.5 2016 2 6 7 64 23 44.4 2016 2 7 8 69 34 49.8 2016 2 8 9 72 29 50 2016 2 9 10 72 25 46.8 2016 2 10 11 73 24 46 2016 2 11 12 69 22 44.4 2016 2 12 13 73 24 46.1 2016 2 13 14 68 26 47.3 2016 2 14 15 72 30 52.2 2016 2 15 16 75 29 50.4 2016 2 16
ans = 31x5 table
Day Maximum Temp Minimum Temp Average Temp YMD ___ ____________ ____________ ____________ ____________________ 1 60 30 46 1981 3 1 2 59 27 42 1981 3 2 3 59 21 39 1981 3 3 4 56 38 47 1981 3 4 5 59 23 42 1981 3 5 6 64 21 42.5 1981 3 6 7 67 34 50.5 1981 3 7 8 69 28 47.5 1981 3 8 9 69 47 57 1981 3 9 10 64 51 58.5 1981 3 10 11 69 40 54.5 1981 3 11 12 70 30 51 1981 3 12 13 61 40 50.5 1981 3 13 14 57 43 49 1981 3 14 15 49 40 44.5 1981 3 15 16 45 36 39.5 1981 3 16
ans = 31x5 table
Day Maximum Temp Minimum Temp Average Temp YMD ___ ____________ ____________ ____________ ____________________ 1 44 35 40.5 1982 3 1 2 61 31 46 1982 3 2 3 59 24 42 1982 3 3 4 50 43 45.5 1982 3 4 5 51 38 44.5 1982 3 5 6 55 38 46.5 1982 3 6 7 66 28 47 1982 3 7 8 66 32 48 1982 3 8 9 66 27 47.5 1982 3 9 10 62 30 47 1982 3 10 11 66 36 51 1982 3 11 12 55 35 45 1982 3 12 13 60 21 41.5 1982 3 13 14 66 27 46.5 1982 3 14 15 71 38 53 1982 3 15 16 63 40 51.5 1982 3 16
ans = 31x5 table
Day Maximum Temp Minimum Temp Average Temp YMD ___ ____________ ____________ ____________ ____________________ 1 77 33 54 2016 3 1 2 76 32 52.6 2016 3 2 3 78 30 52.7 2016 3 3 4 71 35 51.5 2016 3 4 5 74 29 53 2016 3 5 6 68 41 57.8 2016 3 6 7 60 30 50.7 2016 3 7 8 47 27 37.2 2016 3 8 9 63 22 44.9 2016 3 9 10 67 29 49.7 2016 3 10 11 76 27 53.5 2016 3 11 12 72 38 56.6 2016 3 12 13 60 38 48.4 2016 3 13 14 61 28 48.1 2016 3 14 15 66 35 52.6 2016 3 15 16 71 25 48.3 2016 3 16
for k = 1:numel(T) % Loop To Remove 29-Feb
if eomday(T{k}.YMD(:,1), 2) ~= 29
Lv = (T{k}.YMD(:,2) == 2) & (T{k}.YMD(:,3) == 29);
T{k}(Lv,:) = [];
if nnz(Lv) % Optional 'if' Block
fprintf('Feb 29 removed from %s\n', fn{k})
end
end
end
Feb 29 removed from temp_summary.05.02_1981.txt Feb 29 removed from temp_summary.05.02_1982.txt
T{:}
ans = 28x5 table
Day Maximum Temp Minimum Temp Average Temp YMD ___ ____________ ____________ ____________ ____________________ 1 57 12 34.5 1981 2 1 2 58 19 38.5 1981 2 2 3 59 17 37 1981 2 3 4 59 12 35.5 1981 2 4 5 50 12 31.5 1981 2 5 6 54 31 42.5 1981 2 6 7 60 13 36.5 1981 2 7 8 51 29 40 1981 2 8 9 52 36 44 1981 2 9 10 59 24 41.5 1981 2 10 11 61 36 48.5 1981 2 11 12 67 28 46.5 1981 2 12 13 63 21 42 1981 2 13 14 63 29 46 1981 2 14 15 70 26 47 1981 2 15 16 72 29 51.5 1981 2 16
ans = 28x5 table
Day Maximum Temp Minimum Temp Average Temp YMD ___ ____________ ____________ ____________ ____________________ 1 51 32 42.5 1982 2 1 2 52 24 39 1982 2 2 3 59 23 40 1982 2 3 4 45 27 37 1982 2 4 5 41 16 28.5 1982 2 5 6 48 10 28 1982 2 6 7 48 8 27 1982 2 7 8 52 20 36 1982 2 8 9 50 19 33.5 1982 2 9 10 35 30 33.5 1982 2 10 11 54 31 42.5 1982 2 11 12 56 27 40.5 1982 2 12 13 60 27 43.5 1982 2 13 14 63 35 48 1982 2 14 15 66 31 47.5 1982 2 15 16 70 40 56 1982 2 16
ans = 29x5 table
Day Maximum Temp Minimum Temp Average Temp YMD ___ ____________ ____________ ____________ ____________________ 1 40 27 35.6 2016 2 1 2 40 20 29.1 2016 2 2 3 44 18 29.9 2016 2 3 4 50 22 35.6 2016 2 4 5 55 22 37.8 2016 2 5 6 59 22 39.5 2016 2 6 7 64 23 44.4 2016 2 7 8 69 34 49.8 2016 2 8 9 72 29 50 2016 2 9 10 72 25 46.8 2016 2 10 11 73 24 46 2016 2 11 12 69 22 44.4 2016 2 12 13 73 24 46.1 2016 2 13 14 68 26 47.3 2016 2 14 15 72 30 52.2 2016 2 15 16 75 29 50.4 2016 2 16
ans = 31x5 table
Day Maximum Temp Minimum Temp Average Temp YMD ___ ____________ ____________ ____________ ____________________ 1 60 30 46 1981 3 1 2 59 27 42 1981 3 2 3 59 21 39 1981 3 3 4 56 38 47 1981 3 4 5 59 23 42 1981 3 5 6 64 21 42.5 1981 3 6 7 67 34 50.5 1981 3 7 8 69 28 47.5 1981 3 8 9 69 47 57 1981 3 9 10 64 51 58.5 1981 3 10 11 69 40 54.5 1981 3 11 12 70 30 51 1981 3 12 13 61 40 50.5 1981 3 13 14 57 43 49 1981 3 14 15 49 40 44.5 1981 3 15 16 45 36 39.5 1981 3 16
ans = 31x5 table
Day Maximum Temp Minimum Temp Average Temp YMD ___ ____________ ____________ ____________ ____________________ 1 44 35 40.5 1982 3 1 2 61 31 46 1982 3 2 3 59 24 42 1982 3 3 4 50 43 45.5 1982 3 4 5 51 38 44.5 1982 3 5 6 55 38 46.5 1982 3 6 7 66 28 47 1982 3 7 8 66 32 48 1982 3 8 9 66 27 47.5 1982 3 9 10 62 30 47 1982 3 10 11 66 36 51 1982 3 11 12 55 35 45 1982 3 12 13 60 21 41.5 1982 3 13 14 66 27 46.5 1982 3 14 15 71 38 53 1982 3 15 16 63 40 51.5 1982 3 16
ans = 31x5 table
Day Maximum Temp Minimum Temp Average Temp YMD ___ ____________ ____________ ____________ ____________________ 1 77 33 54 2016 3 1 2 76 32 52.6 2016 3 2 3 78 30 52.7 2016 3 3 4 71 35 51.5 2016 3 4 5 74 29 53 2016 3 5 6 68 41 57.8 2016 3 6 7 60 30 50.7 2016 3 7 8 47 27 37.2 2016 3 8 9 63 22 44.9 2016 3 9 10 67 29 49.7 2016 3 10 11 76 27 53.5 2016 3 11 12 72 38 56.6 2016 3 12 13 60 38 48.4 2016 3 13 14 61 28 48.1 2016 3 14 15 66 35 52.6 2016 3 15 16 71 25 48.3 2016 3 16
I just did this for the challenge! This should now produce the desired results.
.

Sign in to comment.

More Answers (0)

Categories

Find more on MATLAB in Help Center and File Exchange

Tags

Products


Release

R2020b

Community Treasure Hunt

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

Start Hunting!