When trying to analyze multiple txt files from 1981-1983 using uigetfile, I get the error "unable to find or open temp_summary.01.1981". Check the path and filename"

1 view (last 30 days)
I am trying to load multiple text files that has 4 columns (Day, High, Low, Average Temperature) and simultaneously compare each day's high, low, and average temperature of January 1st 1981 against January 1st 1982 through January 1st 1983 then repeat each step for January 2nd through December 31. This is to be in an array where I can find the max high, min low, low high, and high low temperatures and the corresponding date that it occurred. Loading the files is fine, but running it through the loop is an issue.
[file_list, path_n] = uigetfile('*.txt', 'Temperature Climatology', 'MultiSelect', 'on');
startYear = 1981;
endYear = 1983;
day = [];
highTemps = [];
lowTemps = [];
avgTemps = [];
for year = startYear:endYear
for month = 1:12
for day = 1:31
filename = sprintf('temp_summary.%05d.%02d.%02d_%d.txt', month, year);
data = readtable(filename); <---------- this is where my error lies
dayData = data(data(:,1) == day,:);
highTemp = max(dayData(:,2));
lowTemp = min(dayData(:,3));
avgTemp = mean(dayData(:,4));
highTemps(end+1) = highTemp;
lowTemps(end+1) = lowTemp;
avgTemps(end+1) = avgTemp;
end
end
end
highestHighTemp = max(highTemps);
lowestLowTemp = min(lowTemps);
lowestHighTemp = min(highTemps);
highestLowTemp = max(lowTemps);
monthlyHighAvg = [];
monthlyLowAvg = [];
monthlyAvgTemp = [];
for month = 1:12
monthlyHighAvg(end+1) = mean(highTemps(month:12:end));
monthlyLowAvg(end+1) = mean(lowTemps(month:12:end));
monthlyAvgTemp(end+1) = mean(avgTemps(month:12:end));
end
moths = 1:12;
figure;
subplot(3,1,1);
plot(months,monthlyHighAvg, 'r');
title('Monthly Average High Temperature');
xlabel('Month');
ylabel('Temperature (°C)');
subplot(3,1,2);
plot(months,monthlyLowAvg, 'b');
title('Monthly Average Low Temperature');
xlabel('Month');
ylabel('Temperature (°C)');
subplot(3,1,3);
plot(months, monthlyAvgTemp, 'g');
title('Monthly Average Temperature');
xlabel('Month');
ylabel('Temperature (°C)');
  6 Comments
Walter Roberson
Walter Roberson on 11 Oct 2023
highTemp = max(dayData.Var2);
lowTemp = min(dayData.Var3);
avgTemp = mean(dayData.Var4);
MATLAB is not being fininicky: MATLAB is being consistent.
Imagine you had a business ledger, and you extracted February 2022 information from it. Would the result be a (smaller) business ledger, or did the action of extracting some rows result in something that is not a business ledger but is something else (that is still structured with multiple columns of a variety of types) ? Now extract from that the columns having to do with date and postage expenses: is the resulting two-column thing with different types not also a business ledger? Now from that, do the same extraction process you used before to extract just the postage expense column: is the resulting one-column result not also a business ledger? If you used the same extraction process then the column will still have a name ("Postage Expenses") and associated values. If you want just the values, you would have to use a different extraction process -- one that left out the column name and just had the values.
Your code was doing the equivalent of using the extraction process that gets multiple columns data(data.Var1 == day,:) complete with headings, but was then expecting that if you used the same extraction process to extract a single column, that the result would contain just the values, where MATLAB says "when you use that extraction process, the result is always a table, and you need to use a different extraction process if you want just the content without the headers."
Could Mathworks have designed table objects such that if you used () notation to extract multiple columns that the result would be a table, but that if you used () notation to extract exactly one column, that the result would be the content without the header? Yes, of course it could have designed it that way.
But consider for example if you gave the task of extracting all of the table columns that show Overdraft, and you do not know ahead of time how many there are. Under the hypothetical design, if there happened to be multiple matching columns, then the result would be (hypothetically) be a table with the associated column names, and you would be able to tell what the overdraft pertained to. But if there happened to be exactly one matching column, then with that hypothetical design, the result would have to be just the content of the column without the header -- and you would not be able to tell what the data pertained to. You would not be able to predict whether the datatype returned would be table or content, so you would have to check class() of what was returned. And for the case where you wanted the headers left intact you would need to create an additional new extraction syntax for the case where you wanted to preserve the table structure even if it happened to be only a single column that was extracted.
It is a much cleaner design all around with the current syntax, where () of a table always results in a table, and you can optionally use {} indexing or dot indexing if you want to get at the contents of the columns.

Sign in to comment.

Answers (1)

Walter Roberson
Walter Roberson on 10 Oct 2023
[file_list, path_n] = uigetfile('*.txt', 'Temperature Climatology', 'MultiSelect', 'on');
You are ignoring both outputs of that
filename = sprintf('temp_summary.%05d.%02d.%02d_%d.txt', month, year);
data = readtable(filename); <---------- this is where my error lies
and you are trying to read from a file in the current directory, whatever the current directory happens to be.
I suspect you should instead be usiing a uigetdir call, and that you should be using fullfile to put that directory together with the sprintf() result to get the name of the file to readtable()
By the way, remember to check whether the output of uigetdir() is character or not. If it is not character then the user used the "cancel" option of uigetdir(). For uigetfile() the situation is slightly more complicated: if the user cancels uigetfile() then the first output ( file_list in your code) will be numeric; if the user selects exactly one file, then the first output would be char; if the user selects more than one file, then the first output will be cell array of character vector. So after testing whether the output is numeric to check for cancel, use cellstr on the variable: if the variable is char then cellstr() will wrap it in a cell, and if the variable is already a cell then cellstr() will return it unchanged.

Categories

Find more on Loops and Conditional Statements in Help Center and File Exchange

Products


Release

R2023a

Community Treasure Hunt

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

Start Hunting!