楼主: intheangel
13083 13

[原创博文] SAS能自己编写函数么? [推广有奖]

  • 3关注
  • 89粉丝

VIP

副教授

25%

还不是VIP/贵宾

-

威望
1
论坛币
49842 个
通用积分
6.1883
学术水平
152 点
热心指数
168 点
信用等级
122 点
经验
12931 点
帖子
480
精华
0
在线时间
475 小时
注册时间
2013-11-22
最后登录
2023-6-28

初级热心勋章

+2 论坛币
k人 参与回答

经管之家送您一份

应届毕业生专属福利!

求职就业群
赵安豆老师微信:zhaoandou666

经管之家联合CDA

送您一个全额奖学金名额~ !

感谢您参与论坛问题回答

经管之家送您两个论坛币!

+2 论坛币
偶然情况下载help里面看到的一个过程步proc fcmp;就到网上查了些资料,原来SAS也可以编写自己的function并调用,可以使复杂的函数瞬间变简单有木有!!!

  1. proc fcmp outlib=function.funcsol.conversion
  2.   function change(lb);
  3.   kg=lb/2.2;
  4.   return (kg);
  5.   endsub;
  6.   run;
复制代码
恭喜大家,这样已经定义了一个属于你自己的函数了,名字叫做change,储存在function.funcsol.conversion 里面;需要注意的是储存的文件夹,也就是function.funcsol.conversion 一定是由三个目录组成的,WHY?
大家可以定义了这个函数之后自己去打开文件看一下,首先是主文件夹function(相当于work), 然后是funcsol(相当于数据集),
而conversion就相当于数据集里的索引了,我个人觉得SAS储存函数还是与储存数据是一样的,把编译了的函数储存在数据集里相当于,个人理解,希望大神指正,这样想便于理解嘛;

语法方面并不是很复杂,我就随便说一下;
相当于do循环有end;
function 有 endsub;如果大家会VB的话,对sub肯定不陌生吧?打VBA天天打有木有~~~
剩下的就简单了,定义一个变量,计算,然后返回计算出来的值,函数结束;


接下来就和format一样,(或者是matlab里面的path),你要告诉SAS到哪里去找你定义的函数;

  1. options cmplib=(function.funcsol);
复制代码
OK, 这样子SAS应该已经知道到哪里去找了;
接下来试一下效果:
  1. data a;
  2. set sashelp.class(keep=name age weight);
  3. kilos=change(weight);
  4. run;
复制代码


这样我们就成功的调用了自己定义的函数;

最简单的例子就是这样了,接下来是进阶教程:
  1. proc fcmp outlib=function.funcsol.conversions;
  2.         function lb2kgc(lb) $;
  3.                 length kg $10;
  4.                 kg = catt(put((lb/2.2),6.2),'kg');
  5.                 return (kg);
  6.         endsub;
  7. run;
复制代码
这个是什么?和前面不同的只有一点,就是return的不是一个数值型变量而是一个字符型变量;
SO,和定义变量一样,加一个 $ 就好;
其他的语法都是一样的,只是一个catt的连接函数而已;

  1. options cmplib=(function.funcsol);

  2. data b;
  3.         set sashelp.class(keep=name age weight);
  4.         kilos=change(weight);
  5.         kg_c=lb2kgc(weight);
  6. run;
复制代码
一样的,试一下;

  1. proc fcmp outlib=function.funcsol.conversions;
  2.         function bmi(lb,ht);
  3.                 return((lb*703)/(ht*ht));
  4.         endsub;
  5.         run;

  6. options cmplib=(function.funcsol);

  7. data bmi;
  8. set sashelp.class(keep=name age weight height);
  9. bmi=bmi(weight,height);
  10. run;
复制代码
OK,两个自变量,right?


接下来两个例子我觉得写得爆赞,可以一窥函数定义的妙处所在;
  1. proc fcmp outlib=function.funcsol.conversions;
  2.         subroutine biomassindex(w,h,b);
  3.                 outargs b;
  4.                 b= ((w*703)/(h*h));
  5.         endsub;
  6.         run;

  7. options cmplib=(function.funcsol);

  8. data bmi;
  9.         set sashelp.class(keep=name age weight height);
  10.         bmindex=.;
  11.         call biomassindex(weight,height,bmindex);
  12. run;
复制代码
几个重要一点的point;
1、 subroutine 这里可以把自变量和return值放在一起;然后通过 outargs来确定输出值是哪一个;看看例子大家一定会明白吧,所以用一个 call function 就可以完成对输出值的赋值;

  1. proc fcmp outlib=function.funcsol.conversions;
  2.         function fromto(code $,v);
  3.                 if upcase(code)='LB2KG' then r=V/2.2;
  4.                 else if upcase(code)='KG2LB' then r=v*2.2;
  5.                 else r=.;
  6.                 return (r);
  7.         endsub;
  8.         run;

  9. option cmplib=(function.funcsol);

  10. data conv;
  11.         set sashelp.class(keep=name age weight);
  12.         kilos=fromto('lb2kg',weight);
  13.         pounds=fromto('kg2lb',kilos);
  14.         run;
复制代码
没有错,函数里面是可以用逻辑语句的,想怎么编就怎么编,接下来大家可能会想怎么样才能够做的更复杂,接下来的例子就是在函数里引入macro, macro本来就是为了使语句更加简化而生的,碰上个一样目的的函数过程步,不能再简化了有木有~~

  1. %macro printit();
  2. %put &lib &dsn;
  3.         %let lib = %sysfunc(dequote(&lib));
  4.         %let dsn = %sysfunc(dequote(&dsn));
  5.         %let num = %sysfunc(dequote(&num));
  6.         %if &num = %then %let num=max;
  7.         title2 "&lib..&dsn";
  8.         title3 "first &num observations";
  9.         proc print data=&lib..&dsn(obs=&num);
  10.                 run;
  11. %mend printit;

  12. proc fcmp outlib=function.funcsol.utilities;
  13.         subroutine printN(lib $, dsn $, num);
  14.                 rc=run_macro('printit',lib,dsn,num);
  15.         endsub;
  16.         run;
复制代码
这里有一个错误使用macro的误区,我来说说我的看法吧,如果你在fcmp里面使用%macro来调用宏的话,就会存在一个编译错误的问题,具体的机制我也不甚清楚,但是可以肯定的是,这样子的宏是没法编译的,因为编译函数我觉得可能在编译宏之前,那样函数的编译就会出错;

所以使用run_macro ('printit',...);
来输入宏和宏变量;

剩下两个例子我个人觉得有点鸡肋,不过用处还是有的,如果你想定义非常复杂的format的话,这个还是有用的吧;
  1. proc format;
  2.         value pounds2kg
  3.                 other=[change()];
  4.         run;

  5. options cmplib=(function.funcsol);

  6. title2 'Weight in Kg';
  7. proc print data=sashelp.class;
  8.         var name age weight;
  9.         format weight pounds2kg.;
  10.         run;
复制代码
大家看到了,就是起到了一个定义format里面格式的作用,把所有的格式都定义为change里面的return值,但是数据集里的值是不变的;

当然,fcmp是可以输出多个值得,用subroutine就好了不是么?
  1. proc fcmp outlib=function.funcsol.conversions;
  2.         subroutine metric_hwbmi(h,w,mh,mw,bmi);
  3.                 outargs mh,mw,bmi;
  4.                 mh = h*.0254;
  5.                 mw = w*.4536;
  6.                 bmi = mw/(mh*mh);
  7.         endsub;
  8.         run;

  9. options cmplib = (function.funcsol);

  10. data multiple;
  11.         set sashelp.class(keep=name age height weight);
  12.         heightmeters=.;
  13.         weightkilos=.;
  14.         bmi=.;
  15.         call metric_hwbmi(height,weight,heightmeters,weightkilos,bmi);
  16.         run;
复制代码


%sysfunc 和 %call,能调用普通函数的工具当然也能调用我们定义的函数;
  1. options cmplib=(function.funcsol);

  2. %let ht = 69;
  3. %let wt = 112.5;
  4. %let bmi = %sysfunc(bmi(&wt,&ht));
  5. %put &bmi;
复制代码

最后一点,定义的函数怎么去除,easy, delete 掉就好(deletefunc)
  1. proc fcmp outlib=function.funcsol.conversions;
  2.         deletefunc lb2kgc;
  3.         deletefunc biomassindex;
  4.         run;
复制代码

定义了的函数可以一直调用而且也可以给别人使用;
但是根据我自己的试验,这个因为是储存成字符,英文版和中文版定义的函数是不能通用的哦~~~~希望大家能把自己的code写的越来越简单,越来越漂亮~~~~

翻译自:https://bbs.pinggu.org/thread-3102197-1-1.html ——Arthur:L.Carpenter(希望我理解的木有错)
















二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

关键词:observations observation conversion Utilities Carpenter function change return 文件夹 网上

已有 2 人评分经验 学术水平 热心指数 信用等级 收起 理由
eijuhz + 1 + 1 + 1 精彩帖子
dxystata + 20 + 1 + 1 精彩帖子

总评分: 经验 + 20  学术水平 + 2  热心指数 + 2  信用等级 + 1   查看全部评分

本帖被以下文库推荐

我是一只瘦瘦的小猪~~~
╭︿︿︿╮
{/-◎◎-/}
( (oo) )
  ︶︶︶
沙发
sypan_forum 发表于 2014-6-23 23:50:16 |只看作者 |坛友微信交流群
第一次知道还有这个功能,谢谢分享

使用道具

藤椅
Bel-esprit 发表于 2014-6-24 16:30:01 |只看作者 |坛友微信交流群
哇,这个好

使用道具

板凳
barry2000 发表于 2014-11-19 10:39:18 |只看作者 |坛友微信交流群
好东西,感谢分享~~~

使用道具

报纸
海∞燕 在职认证  发表于 2015-1-6 12:06:02 |只看作者 |坛友微信交流群
正需要,非常感谢

使用道具

地板
ttea32 发表于 2015-11-18 10:02:21 |只看作者 |坛友微信交流群
你好~请问索引要事先建立好吗?如果别人要用我的函数,那逻辑库数据集索引是不是也要改成别人SAS里的?重新启动SAS要重新定义函数吗?

使用道具

7
wenling15 发表于 2016-5-17 05:44:03 来自手机 |只看作者 |坛友微信交流群
多谢指点!

使用道具

8
river2537 发表于 2017-9-26 14:57:42 |只看作者 |坛友微信交流群
点赞,用这个求BS隐含波动率妥妥的

使用道具

9
evelyne 发表于 2018-7-4 13:40:00 |只看作者 |坛友微信交流群
谢谢分享 厉害

使用道具

10
learsaas 发表于 2018-7-4 14:08:51 |只看作者 |坛友微信交流群
这是在干嘛?

使用道具

您需要登录后才可以回帖 登录 | 我要注册

本版微信群
加好友,备注cda
拉您进交流群

京ICP备16021002-2号 京B2-20170662号 京公网安备 11010802022788号 论坛法律顾问:王进律师 知识产权保护声明   免责及隐私声明

GMT+8, 2024-4-25 21:37