matlab 倒数第二个位置_有哪些让人相见恨晚的 MATLAB 命令?

使用MATLAB两年多,目前每天工作必备,占坑,有时间再答!

偶尔翻翻一年以前自己写的数据处理的代码,真的要被自己蠢哭,当年真的是too young too naive。废话少说!

1. eval

当处理海量数据,进行计算分析的时候,你就需要打开不同文件夹提取和保存数据。这种情况下,eval函数可以大大提高程序的灵活性。如下:input文件夹下有10个子文件夹a1,a2,...,a10,没个文件夹下都有3个mat文件:Press_l,X_l和Y_l。分别读取数据并对其进行处理,然后输出结果文件:XL_l和Patch_l。代码如下:

clear

clc

number=10;%文件数

%创建输出文件夹 C:\Z目录下output文件夹

system('mkdir C:\Z\output')

for i=1:number %打开不同文件夹下相同的数据

eval(['load C:\Z\input\a',num2str(i),'\Press_l.mat']);

eval(['load C:\Z\input\a',num2str(i),'\X_l.mat']);

eval(['load C:\Z\input\a',num2str(i),'\Y_l.mat']);

...%计算过程 要输出结果 XL_l 和 Patch_l

...

name=['mkdir C:\Z\output\a',num2str(i)];%在同一目录下生成输出文件

system(name);%生成C:\Z\output目录下a*文件夹

str1=['C:\Z\output\a',num2str(i),'\XL_l.mat'];

str2=['C:\Z\output\a',num2str(i),'\Patch_l.mat'];

eval(['save ',str1,' XL_l']);

eval(['save ',str2,' Patch_l']);

end可能有人要说了,我的文件夹名字不规律,怎么办。简单,将你的文件夹名字存到一个cell数组内,然后调用胞元就可以了。代码如下:

clear

clc

str={'a1','b2','c3','d4','e5'};

number=size(str,2);%文件数

%创建输出文件夹 C:\Z目录下output文件夹

system('mkdir C:\Z\output')

for i=1:number %打开不同文件夹下相同的数据

eval(['load C:\Z\input\',str{1,i},'\Press_l.mat']);

eval(['load C:\Z\input\',str{1,i},'\X_l.mat']);

eval(['load C:\Z\input\',str{1,i},'\Y_l.mat']);

...%计算过程 要输出结果 XL_l 和 Patch_l

...

name=['mkdir C:\Z\output\' str{1,i}];%在同一目录下生成输出文件

system(name);%生成C:\Z\output目录下a*文件夹

str1=['C:\Z\output\',str{1,i},'\XL_l.mat'];

str2=['C:\Z\output\',str{1,i},'\Patch_l.mat'];

eval(['save ',str1,' XL_l']);%输出XL_l

eval(['save ',str2,' Patch_l']);%Patch_l

end可能还有人说了,我的文件夹太多,不能一一列举出来怎么办?也好办,用dir函数读取目录下的所有文件夹的名字就可以了。代码如下:

clear

clc

filename=dir('C:\Z');

number=size(filename,1);%文件数

%创建输出文件夹 C:\Z目录下output文件夹

system('mkdir C:\Z\output')

for i=1:number %打开不同文件夹下相同的数据

eval(['load C:\Z\input\',filename(i,1).name,'\Press_l.mat']);

eval(['load C:\Z\input\',filename(i,1).name,'\X_l.mat']);

eval(['load C:\Z\input\',filename(i,1).name,'\Y_l.mat']);

...%计算过程 要输出结果 XL_l 和 Patch_l

...

name=['mkdir C:\Z\output\' filename(i,1).name];%在同一目录下生成输出文件

system(name);%生成C:\Z\output目录下a*文件夹

str1=['C:\Z\output\',filename(i,1).name,'\XL_l.mat'];

str2=['C:\Z\output\',filename(i,1).name,'\Patch_l.mat'];

eval(['save ',str1,' XL_l']);%输出XL_l

eval(['save ',str2,' Patch_l']);%Patch_l

end怎么样,是不是好用到哭!你以为eval函数的功能仅此而已的话,那你又错了!例如,经常会遇到需要求解带参数的方程,而且该方程不能显示表达。如公式:

,k取一系列的值(1~100),求相应的自变量x的值。代码如下:

clc

clear

sym x %定义符号变量

K=1:1:100; %参数赋值

number=size(K,2);

X=zeros(number,1); %定义输出结果

for i=1:number

k=K(i);

str=['x^3+',num2str(sqrt(k)),'*x^(1/2)-',num2str(k),'^2'];

a=solve(str,'x','Real', true);

eval(a)

X(i,:)=ans;

endeval函数的妙用绝不仅仅是这些,当你要重复做一些事的时候,变量名稍有些不同,动一动脑筋,eval函数一般都能解决。先到这,如果觉得对你有所帮助,请左上角,蟹蟹~

---------------------------------------------------------2016.5.3更新---------------------------------------------------------

毕业论文基本定稿,开森!首先回复下评论区@Falccm对eval函数用法的质疑,Why Avoid the eval Function? (http://cn.mathworks.com/help/matlab/matlab_prog/string-evaluation.html),这个帮助文档我之前就看过,但是我要反驳。文档中第一句话“Although the eval function is very powerful and flexible,

it not always the best solution to a programming problem. Code that calls eval is

often less efficient and more difficult to read and debug than code that uses

other functions or language constructs.” eval函数主要存在的问题是效率低、难以调试和阅读等问题,但前提该函数是非常强大和灵活的。答主在两年多的科研和项目中,真真切切被eval函数的强大所折服。在处理多工况数据时,eval函数在简化程序方面是无可替代的。这也是为什么答主首先介绍eval函数的原因。至于效率问题,对于一般的数据处理,几乎都是秒算,谁会在乎那节省的零点几秒!

2. 向量化编程函数:accumarray

Accumarray是matlab向量化编程非常实用的内置函数。基本用法:A = accumarray(subs,val);accumarray是坐标累积函数,subs是坐标,val是对应的坐标值,将坐标值val按相应的坐标subs累加到A对应位置。

举例:我们经常会用有限元软件计算结构受力,需要画应力云图。如图1,直接从软件中导出图片感觉略low,我们可以提取出数据利用专业画图软件如Origin来画出较专业的图片,如图2。

图1 应力云图

图2 应力分布

ANSYS提取节点应力和坐标的过程,定义数组,找到要提取面上的节点编号,得到每个节点的坐标和应力,保存数组然后导出,图3就是导出的数据,每列分别为:结点编号、应力、x坐标、y坐标。

图3 数据格式

数据读取与预处理:这里又用到了eval函数,对于处理不同工况,eval真的很好用。

%接触应力后处理

clear

clc

Case=2;

N=200;

ii=8;

eval(['load C:\Z\资料\Paper\CM2015计算文件\ANSYS_xin\case',num2str(Case),'\AA.mat']);

AA=AA/1e3;

Load=[20,50,80,100,120,150,180,200];

eval(['load C:\Z\资料\Paper\CM2015计算文件\ANSYS_xin\case',num2str(Case),'\',num2str(Load(ii)),'_data.txt']);

x=AA(1)*2/AA(4)+1;%P矩阵x向节点数

y=(abs(AA(2))+abs(AA(3)))/AA(5)+1;%P矩阵y向节点数

ex=X200_data;

XX=(-AA(1):AA(4):AA(1))'*1e3;

YY=(AA(2):AA(5):AA(3))'*1e3;

向量化编程代码:

%%

%向量化编程

tic

X=round(arrayfun(@(x)x/AA(4),ex(:,3)));

Y=round(arrayfun(@(x)x/AA(5),ex(:,4)));

subs=[arrayfun(@(x)x-min(X)+1,X),arrayfun(@(x)x-min(Y)+1,Y)];%坐标

P=accumarray(subs,-ex(:,2));

toc

for循环编程

%%

%for编程

tic

x=round(x);

y=round(y);

X=round(ex(:,3)/AA(4));

Y=round(ex(:,4)/AA(5));

p=zeros(x,y);

a=AA(1)/AA(4)+1;

b=(abs(AA(2)))/AA(5)+1;

a=round(a);

b=round(b);

for i=1:size(ex,1)

p(X(i)+a,Y(i)+b)=-ex(i,2);

end

toc

第一段代码是利用向量化写的,第二段是利用for循环写的,向量化是不是很简洁!

可能有人会说我的有限元网格是任意划分的,提出来的节点坐标写不成矩阵的形式。如下图4,空圆圈代表的是提取的数据,红色节点是我们需要插值得到的点。

图4 散点插值

这里就要介绍下matlab里一个吊炸天的插值函数griddata,griddata是matlab里离散插值的函数。基本用法:vq = griddata(x,y,v,xq,yq)二维插值;vq

= griddata(x,y,z,v,xq,yq,zq)三维插值;假设上边提取出来的应力点是不规则的,就需要进行离散点插值,网格大小选为0.5X0.5,代码如下:

%%

%散点插值

[xq,yq]=meshgrid(-10:0.5:10,-6.5:0.5:9);

zq=griddata(ex(:,3)*1e3,ex(:,4)*1e3,-ex(:,2)*1e3,xq,yq,'linear');

这样就可以粘到专业画图软件中画出高逼格的图片了!

最后,贴一下刚才那两段代码的运行时间:

Elapsed time is 0.054833 seconds. %向量化编程

Elapsed time is 0.003075 seconds. %for循环

WTF~向量化编程居然慢了十多倍!其实,for循环处理量级比较小的循环时,还是比较经济有效的,不要一看到有for循环的编程,就觉得很low,不见得~

“你们这一群小婊砸,不要整天鄙视人家,人家没有这么恐怖啦。你们给我等着,我叫我大表哥去,给你们点color see see~”

预告:接下来会写写并行计算parfor以及for循环编程、向量化编程的计算效率问题,敬请期待~

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值