首页 > 解决方案 > Matlab:如何修复我的代码中的循环以对单元格中的每个表运行特定代码?

问题描述

我有这个代码:

  1. 从我的目录中读取我的 .xlsx 文件
  2. 为日期列中错过的日期创建日期
  3. 为这些日期中的变量设置 NaN
  4. 用下一个好的值填充一些列,用其他一些列的平均值填充一些列。

这是完整的代码:

clear
close all
clc
D = 'C:\Users\Behzad\Desktop\New folder (2)';
filePattern = fullfile(D, '*.xlsx');
file = dir(filePattern);
x = {};
for k = 1 : numel(file)
    baseFileName = file(k).name;
    fullFileName = fullfile(D, baseFileName);
    x{k} = readtable(fullFileName);
    fprintf('read file %s\n', fullFileName);
end
% allDates should be out of the loop because it's not necessary to be in the loop
dt1 = datetime([1982 01 01]);
dt2 = datetime([2018 12 31]);
allDates = (dt1 : calmonths(1) : dt2).';
allDates.Format = 'MM/dd/yyyy';
% 1) pre-allocate a cell array that will store
%   your tables (see note #3)
T2 = cell(size(x)); % this should work, I don't know what x is
% the x is xlsx files and have different sizes, so I think it should be in
% a loop?
% creating loop
for idx = 1:numel(x)
    T = x(idx);
    % 2) This line should probably be T = readtable(x(idx));
    sort = sortrows(T, 8);
    selected_table = sort (:, 8:9);
    tempTable = table(allDates(~ismember(allDates,selected_table.data)), NaN(sum(~ismember(allDates,selected_table.data)),size(selected_table,2)-1),'VariableNames',selected_table.Properties.VariableNames);
    T2 = outerjoin(sort,tempTable,'MergeKeys', 1);
    % 3) You're overwriting the variabe T2 on each iteration of the i-loop.
    % to save each table, do this
    T2(idx) = fillmissing(T2, 'next', 'DataVariables', {'lat', 'lon', 'station_elevation'});
    T2.tm_m(isnan(T2.tm_m)) = mean([T2.tmax_m(isnan(T2.tm_m)), T2.tmin_m(isnan(T2.tm_m))],2);

end

这是错误:

使用 matlab.internal.math.sortrowsParseInputs>legacyParseCOL 时出错(第 106 行) 列排序向量必须包含绝对值介于 1 和第一个参数中的列数之间的整数。matlab.internal.math.sortrowsParseInputs 中的错误(第 29 行)[col,colProvided] = legacyParseCOL(col,n,in2); 排序错误(第 60 行)[col, nanflag, compareflag] = matlab.internal.math.sortrowsParseInputs(A,varargin{:});

我要感谢堆栈溢出,让我有机会与 Matlab 专业人士分享我的问题,因为我只是另一个领域的研究员,想临时使用 Matlab 来解决我的问题。

这是从 Google Drive T2.mat 和我的两个 xlsx 文件下载小样本的链接 。

更新(更多信息)这就是我想要从这段代码中得到的: 总的来说,我有很多我想要处理的 excel (.xlsx) 文件。尽管所有这些中的列数相同,但每个文件中的行数不同。第一点是在我的数据(.xlsx 文件)中,有些日期不存在,例如:(MM:DD/YYYY)

1/1/2010
2/1/2010
3/1/2010
5/1/2010 (you can see 4/1/2010 not exist)

我想为它们创建一个日期行,并为这些日期的相应变量设置 NaN 值。其次,我想按日期(升序)对每个 .xlmx 文件进行排序。第三,我想根据每一列中的下一个好值来填充latlon、列中的空白单元格。station_elevation最后,我想tm_m通过平均列tmax_m和填充列中的 NaN 值tmin_m

标签: matlab

解决方案


您的问题是多层次的,从您代码中的注释中,我看到其他人已经尝试帮助您。我可以给你的一个技巧来解决这样一个多层次的问题是依次解决每个子问题。当你找到所有的小解决方案时,你就可以把所有东西放在一起。

您认为要解决的问题如下:

  1. 从我的目录中读取我的 .xlsx 文件

  2. 为日期列中错过的日期创建日期

  3. 为这些日期中的变量设置 NaN

  4. 用下一个好的值填充一些列,用其他一些列的平均值填充一些列。

我看到的实际问题应按如下顺序排列:

  1. 从给定目录读取单个 .xlsx 文件并将其加载到表中

  2. 填写 lat、lon、station_elevation 列的缺失值 (NaN)

  3. 通过平均列 tmax_m 和 tmin_m 填充 tm_m 列的 NaN 值。如果 tmax_m 或 tmin_m 为 NaN,则为 tm_m 保留 NaN 值

  4. 通过从 1982 01 01] 到 [2018 12 31] 附加一整行 NaN 来添加表格中缺失的日期。

  5. 按日期排序此表

  6. 对目录中的所有文件迭代进程 1 到 5

一旦您解决了从 1 到 5 的步骤,这最后一步实际上与其他所有步骤分开,因为您可以将它捆绑到一个函数中,然后对目录中的所有 .xlxs 文件一遍又一遍地重复它。

这是您的解决方案的逐步构建:

第 1 步:从给定目录中读取单个 .xlsx 文件并将其加载到表中

filename = "Qaen.xlsx";
current_table = readtable(filename);

这非常简单,这意味着当我们在步骤 5 中将整个东西捆绑为一个函数时,我们不必担心遍历所有文件,因为该函数将只处理一个文件。我们可以把它从问题中抽象出来。

第 2 步:填写 lat、lon、station_elevation 列的缺失值 (NaN)

current_table = fillmissing(current_table, 'next', 'DataVariables', {'lat', 'lon', 'station_elevation'});

这很简单,还请注意,您的代码中的 x 实际上不再存在,它被一个变量 current_table 替换,该变量引用我们正在使用的当前表。它更容易解析。

步骤 3:通过平均列 tmax_m 和 tmin_m 为 tm_m 列填充 NaN 值。如果 tmax_m 或 tmin_m 为 NaN,则为 tm_m 保留 NaN 值

% If one of the value tmax and tmin is NaN the mean will stay NaN
mean_tm =  mean([current_table.tmax_m(isnan(current_table.tm_m)), current_table.tmin_m(isnan(current_table.tm_m))],2);
current_table.tm_m(isnan(current_table.tm_m)) = mean_tm;

这里的一些值将是 NaN,因为我们在 2 列矩阵之间取平均值,这正是预期的行为。

第 4 步:通过从 1982 01 01] 到 [2018 12 31] 附加一整行 NaN 来添加表格中缺失的日期。

start_date = datetime([1982 01 01]);
end_date = datetime([2018 12 31]);
allDates = (start_date : calmonths(1) : end_date).';
allDates.Format = 'yyyy-dd-MM';

missing_dates = allDates(~ismember(allDates,current_table.data));
nan_values = NaN(sum(~ismember(allDates,current_table.data)),1);
variable_names = {'data','value'};
tempTable = table(missing_dates, nan_values,'VariableNames',variable_names);
current_table = outerjoin(current_table,tempTable,'MergeKeys', 1);

我将您拥有的一个衬里分解为多个语句,并将它们用作创建表的变量。对于没有错误的代码来说,一个巨大的单行代码很少是一个好的设置。

第 5 步:按日期排序此表

current_table = sortrows(current_table, 8); 

最后,我们就像您之前所做的那样简单地进行排序。

现在,如果我们想在多个文件中重复这个过程,我们需要将步骤 1 到 5 捆绑到一个易于重用的函数中。如果您需要一些有关功能的帮助,请转到此处

1到5的功能捆绑:

function [current_table] = process_xlsx(filename)
    current_table = readtable(filename);

    current_table = fillmissing(current_table, 'next', 'DataVariables', {'lat', 'lon', 'station_elevation'});

    % If one of the value tmax and tmin is NaN the mean will stay NaN
    mean_tm =  mean([current_table.tmax_m(isnan(current_table.tm_m)), current_table.tmin_m(isnan(current_table.tm_m))],2);
    current_table.tm_m(isnan(current_table.tm_m)) = mean_tm;


    % Create a list of all the dates between start date and end date
    start_date = datetime([1982 01 01]);
    end_date = datetime([2018 12 31]);
    allDates = (start_date : calmonths(1) : end_date).';
    allDates.Format = 'yyyy-dd-MM';

    missing_dates = allDates(~ismember(allDates,current_table.data));
    nan_values = NaN(sum(~ismember(allDates,current_table.data)),1);
    variable_names = {'data','value'};
    tempTable = table(missing_dates, nan_values,'VariableNames',variable_names);
    current_table = outerjoin(current_table,tempTable,'MergeKeys', 1);

    current_table = sortrows(current_table, 8); 
end

现在我们可以在第 6 步中重用它!

步骤 6:对目录中的所有文件迭代过程 1 到 5

directory = 'C:\Users\Behzad\Desktop\New folder (2)';
filePattern = fullfile(directory, '*.xlsx');
file = dir(filePattern);
all_tables = cell(1,length(file));
for k = 1 : numel(file)
    baseFileName = file(k).name;
    fullFilename = fullfile(directory, baseFileName);

    fprintf('Processing file %s\n', fullFilename);
    all_tables{k} = process_xlsx(fullFilename);
end

如果我们将所有这些放在一起,我们会在一个脚本中得到以下内容:

% Goal of the script:
% 1)read my .xlsx files from my directory
% 2)creat date for missed dates in a date columns
% 3)set NaN for variables in these dates
% 4) fill some columns with the next good value and fill some columns with an average of some other columns.

% Clear up the workspace, the figures and the command window feed
clear
close all
clc

directory = 'C:\Users\Behzad\Desktop\New folder (2)';
filePattern = fullfile(directory, '*.xlsx');
file = dir(filePattern);
all_tables = cell(1,length(file));
for k = 1 : numel(file)
    baseFileName = file(k).name;
    fullFilename = fullfile(directory, baseFileName);

    fprintf('Processing file %s\n', fullFilename);
    all_tables{k} = process_xlsx(fullFilename);
end



function [current_table] = process_xlsx(filename)
    current_table = readtable(filename);

    current_table = fillmissing(current_table, 'next', 'DataVariables', {'lat', 'lon', 'station_elevation'});

    % If one of the value tmax and tmin is NaN the mean will stay NaN
    mean_tm =  mean([current_table.tmax_m(isnan(current_table.tm_m)), current_table.tmin_m(isnan(current_table.tm_m))],2);
    current_table.tm_m(isnan(current_table.tm_m)) = mean_tm;


    % Create a list of all the dates between start date and end date
    start_date = datetime([1982 01 01]);
    end_date = datetime([2018 12 31]);
    allDates = (start_date : calmonths(1) : end_date).';
    allDates.Format = 'yyyy-dd-MM';

    missing_dates = allDates(~ismember(allDates,current_table.data));
    nan_values = NaN(sum(~ismember(allDates,current_table.data)),1);
    variable_names = {'data','value'};
    tempTable = table(missing_dates, nan_values,'VariableNames',variable_names);
    current_table = outerjoin(current_table,tempTable,'MergeKeys', 1);

    current_table = sortrows(current_table, 8); 
end

希望能帮助到你!


推荐阅读