在MATLAB中对可变数量的工作空间元素执行操作

时间:2018-01-06 05:54:23

标签: matlab function

新的MATLAB用户如果这看起来像一个愚蠢的问题,请道歉。我的工作区中有以下变量列表(双打):

E1_01Strain  E1_06Strain  E1_07Strain  E1_08Strain  E1_09Strain  E1_10Strain  
E1_01Stress  E1_06Stress  E1_07Stress  E1_08Stress  E1_09Stress  E1_10Stress

这些是数字列表。我想从每个变量中删除最后n个元素。我可以用命令

来做
E1_01Strain = E1_01Strain(1:end-100)

但这是不切实际的,因为后来我将不得不在很多很多类似的变量上做这件事。因此,我想编写一个函数,接受工作空间变量的列表作为输入(如,我突出显示我想要的变量并拖放到函数输入中)并从每个n元素中删除。

我知道我可以写一个这样的函数:

function [X1, X2, X3, X4] = Remove_n_elements[n, X1, X2, X3, X4]
 X1 = X1(1:end-100);
 X2 = X2(1:end-100);
 X3 = X3(1:end-100);
 X4= X4(1:end-100);
end

但这意味着我每次都必须更改函数中的输入,输出和代码行数。我确信有更好的方法可以做到,但我无法理解。

我一直认为可能有办法通过循环所有输入来实现它,但我无法让它工作,因为(据我所知)我需要创建一个输入列表然后只对该列表的元素执行操作,而不是输入本身。

我正在查看Passing A Variable Number of Arguments into a Function并使用来自https://www.mathworks.com/help/matlab/matlab_prog/parse-function-inputs.html的inputParser,但由于我是MATLAB的新手,我不确定如何在我的情况下使用它。

2 个答案:

答案 0 :(得分:1)

我使用了il_raffa提供的代码,但是听从了他的建议并回过头来重新考虑了脚本的功能。经过一番挖掘后,我编写了以下脚本,完全符合我的需要。此脚本从文件夹中的所有.csv文件中提取列des_cols,并将它们一起绘制。然后再绘制平均值。

files = dir('*.csv'); % navigate to the folder that you want to run the script on in MATLAB
avgStress = [];
avgStrain = [];
set(groot, 'DefaultLegendInterpreter', 'none') % the names of my .csv files have underscores that I want to see in the legend, if you don't want this then comment this line
hold on; %comment this and hold off further down if you want separate plots for every .csv
for file = files'
    csv = xlsread(file.name);
    [n,s,r] = xlsread(file.name);
    des_cols = {'Stress','Ext.1(Strain)'}; % type here the names of the columns you want to extract
    colhdrs = s(2,:);
    [~,ia] = intersect(colhdrs, des_cols);
    colnrs = flipud(ia);
    file.name = n(:, colnrs);
    file.name = file.name(1:end-600,:); % I wanted to remove the last 600 rows but if you want them all, remove the -600
    plot(file.name(:,2),file.name(:,1),'DisplayName',s{1,1});
    avgStress = [avgStress file.name(1:1500,1)]; % calculates the average stress for the first 1500 points, you can change it to whatever you want
    avgStrain = [avgStrain file.name(1:1500,2)];
end
ylabel({'Stress (MPa)'}); % y-axis label
xlabel({'Strain (%)'}); %x-axis label
title({'E_2'}); % title of the plot
legend('show');
hold off; % commment this if you want different plots for all .csv files
avgStress = mean(avgStress,2);
avgStrain = mean(avgStrain,2);
plot(avgStrain,avgStress);

这会创建两个图,一个包含所有原始数据,另一个只包含平均值。我希望这有助于任何可能遇到类似问题的人。

答案 1 :(得分:0)

您可以做的最好的事情是检查SW的体系结构,以避免在Workspace变量上执行此类操作的需要。

那就是:如何创建这些变量?这些变量是从“.mat”文件加载的吗?等

无论如何,为了避免使用eval函数并根据您的情况,可能的方法是:

  • 使用函数who标识varailbes的名称。您可以在调用who时指定变量的根名称,并使用*,例如who('E1*')。确保它适合所需的变量。您还可以使用regexp来更好地完善变量的选择
  • 将这些变量保存在临时.mat文件中:名称(包括临时文件的路径可以使用函数tempname
  • 创建
  • 加载临时.mat文件:这会在工作区中创建一个struct,其字段是您想要调整的变量
  • 调用该函数从结构的字段中删除不需要的元素。该函数必须返回更新的struct
  • 将更新的结构保存在临时文件中
  • 通过指定允许将文件内容作为单个变量加载的选项-struct再次加载临时文件

删除不需要的元素的功能可以如下:

  • 使用函数fieldnames
  • 获取结构字段的nams
  • 使用dynamic field names属性
  • 遍历结构的字段
  • 从字段中删除不需要的元素
  • 返回更新的结构

可能的实施可能是:

代码“在”调用函数之前

% Get the names of the variables
list_var=who('E1*')
% Define the name of a temporary ".mat" file
tmp_file=tempname
% Save the variables in the temporary ".mat" file
save(tmp_file,list_var{:});
% Load the variables in a struct
sel_vars=load(tmp_file);
% Call the function to remove the elements
out_str=Remove_n_elements(8,sel_vars)

删除不需要的元素的功能

function sel_vars=Remove_n_elements(n,sel_vars)
% Get the names of the fields of the struct
var_names=fieldnames(sel_vars)
% Loop over the fields and remove the undesired elements
for i=1:length(var_names)
   sel_vars.(var_names{i})=sel_vars.(var_names{i})(1:end-n)
end

代码“在”调用函数

之后
% Save the updated struct in the temporary ".mat" file
save(tmp_file,'-struct','out_str')
% Load the updated struct as separate variables
load(tmp_file)