Categories
日常应用

七天搞定SAS(二):基本操作(判断、运算、基本函数)

本系列连载文章:

继续,今天开始注重变量操作。

SAS生成新变量

SAS支持基本的加减乘除,值得一提的是它的**代表指数,而不是^。

* Modify homegarden data set with assignment statements;
DATA homegarden;
INFILE 'c:\MyRawData\Garden.dat';
INPUT Name $ 1-7 Tomato Zucchini Peas Grapes;
Zone = 14;
Type = 'home';
Zucchini = Zucchini * 10;
Total = Tomato + Zucchini + Peas + Grapes;
PerTom = (Tomato / Total) * 100;
RUN;
PROC PRINT DATA = homegarden;
TITLE 'Home Gardening Survey';
RUN;

但是如果有缺失值的话,SAS的加法会生成缺失值而不是自动按0处理。为了避免这一点,应该调用sum()函数而不是直接写+。

SAS的函数调用很简单:

AvgScore = MEAN(Scr1, Scr2, Scr3, Scr4, Scr5);
DayEntered = DAY(Date);
Type = UPCASE(Type);

函数有文本类、数字类、日期类等等。

SAS文本类函数

  • ANYALNUM(arg,start):返回第一次出现任意数字或字母的位置,可选开始位置start。
  • ANYALPHA(arg,start):返回第一次出现任意字母的位置,可选开始位置start。
  • ANYDIGIT(arg,start):返回第一次出现任意数字的位置,可选开始位置start。
  • ANYSPACE(arg,start):返回第一次出现任意空白的位置,可选开始位置start。
  • CAT(arg-1,arg-2,...arg-n):连接字符串,留下头尾空白。
  • CATS(arg-1,arg-2,...arg-n):连接字符串,删除头尾空白。
  • CATX('separator-string', arg-1,arg-2,...arg-n):连接字符串,删除头尾空白并用指定标点连接。
  • COMPRESS(arg, 'char'):移除字符串中的空格和可选字符。
  • INDEX(arg, 'string') :返回指定字符在变量中的位置。
  • LEFT(arg) :字符串左对齐。
  • LENGTH(arg):返回字符串长度,不考虑尾部空格。
  • PROPCASE(arg) :首字母大写。
  • SUBSTR(arg,position,n):从字符串中提取指定开始位置指定长度字符。
  • TRANSLATE(source,to-1, from-1,...to-n,from-n):替换字符。
  • TRANWRD(source,from,to) :替换字符串。
  • TRIM(arg):删除尾部空白。
  • UPCASE(arg):替换成大写。

SAS数值函数

  • INT(arg):返回整数。
  • LOG(arg):自然对数。
  • LOG10(arg) :10为底对数。
  • MAX(arg-1,arg-2,...arg-n) :最大值
  • MEAN(arg-1,arg-2,...arg-n) :均值
  • MIN(arg-1,arg-2,...arg-n) :最小值
  • N(arg-1,arg-2,...arg-n) :非缺失值个数
  • NMISS(arg-1,arg-2,...arg-n) :缺失值个数。
  • ROUND(arg, round-off-unit) :保留几位小数。
  • SUM(arg-1,arg-2,...arg-n):求和。

SAS日期函数

  • DATEJUL(julian-date) :标准julian日期到SAS日期。
  • DAY(date):返回「日」。
  • MDY(month,day,year) :年月日到SAS日期。
  • MONTH(date) :返回「月」。
  • QTR(date):返回季度。
  • TODAY():今日
  • WEEKDAY(date):返回周几(周日为1)。
  • YEAR(date):返回「年」。
  • YRDIF(start-date,end- date,’ACTUAL’):返回相差年份。

SAS中判断语句

如果,则:

IF then: IF Model = 'Mustang' THEN Make = 'Ford';

还可以执行多项命令,需要嵌套do;可以用and和or:

IF Year IF Model = 'Corvette' OR Model = 'Camaro' THEN Make = 'Chevy';
IF Model = 'Miata' THEN DO;
Make = 'Mazda';
Seats = 2;
END;

还可以if else:

IF Cost = . THEN CostGroup = 'missing';
ELSE IF Cost ELSE IF Cost ELSE CostGroup = 'high';

用if可以选择数据子集:

IF Sex = 'f'; IF Sex = 'm' THEN DELETE;

SAS中保留和累加

比如要求累加值(等价于R里面的cumsum),需要:

* Using RETAIN and sum statements to find most runs and total runs;
DATA gamestats;
INFILE 'c:\MyRawData\Games.dat';
INPUT Month 1 Day 3-4 Team $ 6-25 Hits 27-28 Runs 30-31;
RETAIN MaxRuns;
MaxRuns = MAX(MaxRuns, Runs);
RunsToDate + Runs;
RUN;
PROC PRINT DATA = gamestats;
TITLE "Season's Record to Date";
RUN;

看一眼最终数据:

2013-12-09 16_37_58-The Little SAS Book(Fourth).PDF - Adobe Reader

累加效果出来了~还有一栏是迄今最大值。这也是我觉得sas和R很不同的一点:sas是指针式操作,一行行往下读;而在R里面我们更多是向量或者矩阵式运算,感觉还是有所区别的...

SAS的数组操作

这个就更有点矩阵的味道了,不过还是偶尔感觉怪怪的...感觉数据整理和操纵方面,SAS还是比不上R灵活...

例子为替换为缺失值:

* Change all 9s to missing values;
DATA songs;
INFILE 'c:\MyRawData\WBRK.dat';
INPUT City $ 1-15 Age domk wj hwow simbh kt aomm libm tr filp ttr;
ARRAY song (10) domk wj hwow simbh kt aomm libm tr filp ttr;
DO i = 1 TO 10;
IF song(i) = 9 THEN song(i) = .;
END;
RUN;
PROC PRINT DATA = songs;
TITLE 'WBRK Song Survey';
RUN;

这样9就全部替换为缺失值了。把后面10列认为是一个数组,可以直接操作。

SAS还有若干变量名的快捷方式,暂不赘述了...

Categories
日常应用

七天搞定SAS(一):数据的导入、数据结构

标题有些噱头,不过这里的重点是: speak SAS in 7 days。也就是说,知识是现成的,我这里只是要学会如何讲这门语言,而不是如何边学SAS边学模型。顺便发现我最近喜欢写连载了,自从西藏回来后.....

之所以下定决定学SAS,是因为周围的人都在用SAS。为了和同事的沟通更有效率,还是多学一门语言吧。R再灵活,毕竟还是只有少数人能直接读懂。理论上语言是不应该成为障碍的~就像外语一样,多学一点总是好的,至少出门不发怵是不是?

最后一根稻草则是施老师传给我的一个link:http://blog.softwareadvice.com/articles/bi/3-career-secrets-for-data-scientists-1101712/,据说有数据分析师的职业秘笈...我就忍不住去看了看。其中一句话还是蛮有启发的:

如果有人问你要学什么工具,是SAS,R,EXCEL,SQL,SPSS还是?直接回答:所有。

这个答案一方面霸气,一方面也是,何必被工具束缚呢?

这东西宜突击不宜拖延,所以还是集中搞定吧。七天应该是个不错的时间段。

大致分配如下:
1. 熟悉SAS的数据结构,如基本的向量,数据集,数组;熟悉基本的数据类型,如文本,数字。
2. 熟悉基本的数据输入与输出。
3. 熟悉基本的逻辑语句:循环,判断
4. 熟悉基本的数据操作:筛选行列,筛选或计算变量,合并数据集,计算基本统计量,转置
5. 熟悉基本的文本操作函数
6. 熟悉基本的计量模型函数
7. 熟悉基本的macro编写,局部变量与全局变量

其实这大概也是按照我常用的R里面完成的任务来罗列的。基本计划是完成就可以大致了解SAS的语法了,其他的高级功能现用现学吧。

书籍方面,中文的抢了同事的一本《SAS编程与数据挖掘商业案例》,英文的找了一本「Applied Econometrics Using The SAS System」和「The Little SAS Book」,先这么看着吧。

后知后觉的补充:其实这一系列笔记都是先写再发布的,主要是方便我调整顺序什么的。事实证明绝大多数时间我在看(或者更直接的,抄)「The Little SAS Book」这本书,姚老师的《SAS编程与数据挖掘商业案例》简单看了一晚,作为对于SAS语法的预热。最后那本「Applied Econometrics Using The SAS System」更多是看具体模型的用法了,不是熟悉语法的问题了。例子都是第一本little book上的,很好用。

本系列连载文章:

-------笔记开始-------

SAS的数据类型

2013-12-09 16_41_10-The Little SAS Book(Fourth).PDF - Adobe Reader

首先,sas的编程大概就两块:Data和PROC,这个倒是蛮清晰的划分。然后目前关注data部分。

SAS的数据类型还真的只有两种:数字和文本。那么看来日期就要存成文本型了。变量名称后面加$代表文本型。

SAS的数据读入

手动输入这种就不考虑了,先是怎么从本地文件读入。比如我们有文本文件如下:

Lucky 2.3 1.9 . 3.0
Spot 4.6 2.5 3.1 .5
Tubs 7.1 . . 3.8
Hop 4.5 3.2 1.9 2.6
Noisy 3.8 1.3 1.8 1.5
Winner 5.7 . . .

然后SAS里面就可以用

* Create a SAS data set named toads;
* Read the data file ToadJump.dat using list input;
DATA toads;
INFILE ’c:\MyRawData\ToadJump.dat’;
INPUT ToadName $ Weight Jump1 Jump2 Jump3;
RUN;
* Print the data to make sure the file was read correctly;
PROC PRINT DATA = toads;
TITLE ’SAS Data Set Toads’;
RUN;

这样就建立了一个名为toads的临时数据集,然后读入外部文件ToadJump.dat,然后告诉SAS有四个变量,其中第一个是文本型。这样就OK了。缺失值用一个点.标记。

偶尔数据没那么规范,比如长成:

----+----1----+----2----+----3----+----4
Columbia Peaches 35 67 1 10 2 1
Plains Peanuts 210 2 5 0 2
Gilroy Garlics 151035 12 11 7 6
Sacramento Tomatoes 124 85 15 4 9 1

那么就要有点类似正则表达式的感觉,告诉SAS更多的参数:

* Create a SAS data set named sales;
* Read the data file OnionRing.dat using column input;
DATA sales;
INFILE ’c:\MyRawData\OnionRing.dat’;
INPUT VisitingTeam $ 1-20 ConcessionSales 21-24 BleacherSales 25-28
OurHits 29-31 TheirHits 32-34 OurRuns 35-37 TheirRuns 38-40;
RUN;
* Print the data to make sure the file was read correctly;
PROC PRINT DATA = sales;
TITLE ’SAS Data Set Sales’;
RUN;

这样SAS就可以正确的读数据了—类似于excel的导入文本-固定宽度分隔。

再不规则的话,比如有日期型的:

Alicia Grossman 13 c 10-28-2008 7.8 6.5 7.2 8.0 7.9
Matthew Lee 9 D 10-30-2008 6.5 5.9 6.8 6.0 8.1
Elizabeth Garcia 10 C 10-29-2008 8.9 7.9 8.5 9.0 8.8
Lori Newcombe 6 D 10-30-2008 6.7 5.6 4.9 5.2 6.1
Jose Martinez 7 d 10-31-2008 8.9 9.510.0 9.7 9.0
Brian Williams 11 C 10-29-2008 7.8 8.4 8.5 7.9 8.0

那么接下来就是:

* Create a SAS data set named contest;
* Read the file Pumpkin.dat using formatted input;
DATA contest;
INFILE ’c:\MyRawData\Pumpkin.dat’;
INPUT Name $16. Age 3. +1 Type $1. +1 Date MMDDYY10.
(Score1 Score2 Score3 Score4 Score5) (4.1);
RUN;
* Print the data set to make sure the file was read correctly;
PROC PRINT DATA = contest;
TITLE ’Pumpkin Carving Contest’;
RUN;

就是说,name是一个长度为16的字符;age是长度为3、无小数点的数字;+1跳过空列;type是长度为1的文本;date是MMDDYY长度为10的日期;score1-5是长度为4,小数部分为1位的数字。

还有若干更复杂的,可以遇到时侯回来查手册。此外还有@可用来直接指定开始读的列。鉴于我接触的数据一般比较规范,这些就不细看了。

此外SAS可以指定开始读的行数,读取的行数等。

DATA icecream;
INFILE ’c:\MyRawData\IceCreamSales.dat’ FIRSTOBS = 3;
INPUT Flavor $ 1-9 Location BoxesSold;
RUN;

SAS读取CSV数据

以我最关心的CSV文件为例,如下数据:

Lupine Lights,12/3/2007,45,63,70,
Awesome Octaves,12/15/2007,17,28,44,12
"Stop, Drop, and Rock-N-Roll",1/5/2008,34,62,77,91
The Silveyville Jazz Quartet,1/18/2008,38,30,42,43
Catalina Converts,1/31/2008,56,,65,34

只需要:

DATA music;
INFILE ’c:\MyRawData\Bands.csv’ DLM = ’,’ DSD MISSOVER;
INPUT BandName :$30. GigDate :MMDDYY10. EightPM NinePM TenPM ElevenPM;
RUN;
PROC PRINT DATA = music;
TITLE ’Customers at Each Gig’;
RUN;

其实,貌似更简单的办法是:

DATA music;
INFILE ’c:\MyRawData\Bands.csv’ DLM = ’,’ DSD MISSOVER;
INPUT BandName :$30. GigDate :MMDDYY10. EightPM NinePM TenPM ElevenPM;
RUN;
PROC PRINT DATA = music;
TITLE ’Customers at Each Gig’;
RUN;

好吧,import果然更直接一点...excel文件也可以如法炮制。

SAS读取excel数据

* Read an Excel spreadsheet using PROC IMPORT;
PROC IMPORT DATAFILE = 'c:\MyExcelFiles\OnionRing.xls' DBMS=XLS OUT = sales;
RUN;
PROC PRINT DATA = sales;
TITLE 'SAS Data Set Read From Excel File';
RUN;

如果需要SAS永久存着这些数据,则需要先指定libname:

LIBNAME plants ’c:\MySASLib’;
DATA plants.magnolia;
INFILE ’c:\MyRawData\Mag.dat’;
INPUT ScientificName $ 1-14 CommonName $ 16-32 MaximumHeight
AgeBloom Type $ Color $;
RUN;

后期就可以直接调用啦:

LIBNAME example ’c:\MySASLib’;
PROC PRINT DATA = example.magnolia;
TITLE ’Magnolias’;
RUN;

SAS 读取Teradata数据

最后就是从teradata里面读数据,可以利用teradata fastexport特性:

libname tra Teradata user=terauser pw=XXXXXX server=boom;
proc freq data=tra.big(dbsliceparm=all);
table x1-x3;
run;

等价于:

proc sql;
connect to teradata(user=terauser password=XXXXXX server=boom dbsliceparm=all);
select * from connection to teradata
(select * from big);
quit;

暂时没有fastload的需求,就先这样吧。可以参见SAS的TD手册:http://support.sas.com/resources/papers/teradata.pdf

本系列连载文章:

 

Categories
Wordpress 网站建设

病毒凶残 -_-||

今天终于把所有的sites都搬到新的服务器上去了...各种凶残的病毒残留痕迹,防不胜防...索性一切wordpress的插件什么的都是重新安装的,哎。

祈求一下,让我清净两天吧。最近事事儿已经够多的了,不要再来了。

 

Categories
Uncategorized 网站建设

落园小小的挪动

越是我懒得打理落园,越是有病毒木马什么的来骚扰,实在是不胜其烦...于是小小的挪窝了一下...

找了一个容量不怎么大但是还过得去的虚拟主机,然后三下五除二把落园搬过来了。这次不牵扯什么301永久重定向之类的,搬起来倒是也方便,轻车熟路的就挪好窝了。话说这也是这"鹊占鸠巢"两年多以后,第一次被迫无奈的乖乖挪出来(多谢yihui兄当年危难关头的仗义收留啊)...这个病毒实在是汹涌的紧,着实惹不起啊。看着Yihui兄连年又是跟code奋战又是跟客服打口水仗,也真是辛苦。最后他还是劝大家挪到其他地方,比如Github...可是我就一直没有心思彻底折腾,直到这次放假不动手不行了啊(p.s. 在家里用着十年前生产的古董台式机、只有xp自带的notepad作为文本编辑器的孩子,伤不起啊~无高亮无折叠也就罢了,居然还会自动取消断行!一堆代码就那么华丽丽的堆在一行!)。

看着大家都去玩新潮的github了,我也口水开始积攒,多么适合装装威风啊。yanping兄为了鼓励我挪过去,甚至都帮我改好了模板...可是我还是不想抛弃wordpress,哎~原因大致是比较感性的居多(就像一个流传很久的笑话:某宅男被女神问到什么笔记本好,于是他花了一晚上功夫在京东上看遍了各种本本,女神问的各种问题对答如流,最终给出了各种情况下的推荐。过几天见到女神,手里抱着个mac air,故大大惊讶之--这明明不符合当时的对话嘛,所以没有推荐啊。结果女神只是很简单的说了一句话--我还是觉得mac比较漂亮。据说还有很多男同志一直不服气被指责为只看表面的好色之徒--你们女人买车的时候不也是只看外观的么?靠~凭什么大爷我走在路上多瞄了两眼美女就成色狼了~)(p.s. 我觉得上文中那个注定孤独终老的宅男真是咎由自取啊,女神来问就应该乖乖的有钱出钱无钱卖肾什么的都好去买个mac主动送上去的嘛~笨死的都是)

好吧,其实我的理由也没有高尚到哪里去...

首先呢,看了一堆git架博客的教程,觉得那些"弄潮儿"的博客主题风格我真心不喜欢,看着顺眼的有,但绝对没到了看着搬回家也顺眼的程度,所以还是放在人家家里吧,自家不要。

然后呢,其实把现在的主题稍稍打磨一下也就能用了,但是还是不够完美啊...什么相关博文啊之类的,不是动态生成的怎么可以呢?好歹姐姐也接触了一年推荐算法,这种用户体验优化的觉悟还是有的...

再次呢,当初狠心下功夫学PHP和ajax的时候就是觉得这东西可以动态生成页面,真心好。以前的时候一直不知道网页中的表单提交之后是怎么处理的呢,比如最简单的用户注册什么的。git却又把理念倒回去了。虽说三十年河东三十年河西,有人说git这种形式更适合log类,比如blog,但是我每次在那些网站上留言还要用一个第三方的ajax插件的感觉就不爽,哼。我的blog是用来social的,social的啦啦!不是写在那里跟个what's new的软件更新通知似的。把facebook搞成全静态的还好玩吗,对吧?我还是不认同blog是更适合静态文件系统这一理念的...

最后呢...markdown真心没有写日志的感觉啊!一写md就是一种coding的滋味,不好受不好受,整天上班就是离不开代码,好好的写写blog还不让我舒服点?虽然我也自认代码洁癖有一些,但是还没到受得了markdown的地步(虽然有各种码农出身的小清新小文艺小13B,但还是逃不了码农的劣根本性啊...)。

最后抵触的情绪胜过了理智的那些诸如安全啦,无病毒无宕机,无付费无担心之类的理智理由,也胜过了装腔作势玩弄新潮专业武器的心理,乖乖的还是挪了一个php服务器而已。最后,嗯,其实人家真的变懒了...本来是打算趁机弄个VPS个人主机玩玩的,怎么在这个"云时代"也得有自己的一片云才显得专业嘛,就是那种有shell什么的完全等价于一台服务器而不是一个虚拟空间的。后来想了想不会还要我重新配置apache什么的吧?当年本地装个这些东西都折腾死我了,才不要在服务器上继续折腾自己呢。算了算了...再说还有amazon cloud可以玩呢,实在不行玩玩公司里的cloud也就够过过瘾了。又可见懒人一个。

说了这么多...今天还去yihui的地盘叫嚣什么他是关了太久了终于放出来透透气了(换个难听点的说法就是闷骚),其实我也没好到哪里去...明明就是换了个ip解析地址的小破事儿就能被我朗朗不断的写了这么长一堆...好吧,作为一个在家里百无聊赖终于忍不住抢了老妈的ipad的人,其实已经抱着ipad看了好几天书了,除了睡觉吃饭就是看书。等等。你不会以为我真好好学什么的吧,真学习的话我也不能抱着ipad看啊,怎么也得是几本实体书最次kindle什么的。其实我看的书是小说...恶补了刘建良这位也不知道入不入流的小说家过去两三年写的又臭又长的连载(以前大学的时候貌似经常翻舍友买回来的武侠奇幻杂志什么的),居然耗掉了我那么多个整天。好处也有,看完了爽过了就忘了,完全没记忆,也不会心惊胆颤什么的...好吧长假就是用小说什么的来打发时间的嘛。那个风起云涌的武侠时代还是很让人不时憧憬一下的。

相关文章

Categories
网站建设

落园恢复访问

趁着我出门游玩了几天,病毒就开始肆虐发作,搞得落园首页瘫痪。可怜我只带着iPad出门,眼睁睁的看着落园瘫痪却无能为力,加上格外给力的台风让我滞留宾馆里打牌...真的是越急越没有办法。

看了一眼被感染的情况,又是针对index.php的攻击,一段长长的病毒代码嵌入,哎~ 手动清理文件倒是不麻烦,只是这绝非长久之计...各种病毒什么的,三天一小闹五天一大闹,一个月不让你网站瘫痪一次都不带死心的,真心受不了了。凡事总得有个忍耐的限度啊...

等我睡几天恢复状态后,开始彻底收拾这个问题。到底是继续留在Wordpress、还是象大家一样转战github,还是其他,反正总会有个解决策略的。再感慨一次:

写博客不难,常年写博客也不难,难的在于鼓捣个独立博客远远不只是写写文章这么点破事儿…

落园会不会有一次彻底的构架变动呢?容我好好想一想...好久没写过PHP代码了,天知道还能记得住几个函数……

只是先在这里发发牢骚,喵呜。