怎么让图中曲线看起来更光滑以及相关问题和应用。

 B样条函数, SAS编程绘图, 光滑, 数据预处理, 样条spline  怎么让图中曲线看起来更光滑以及相关问题和应用。已关闭评论
8月 072010
 

有时候我们在做曲线图的时候,得到的点连接图像下面图一样,感觉很毛糙,本来是要反映一种变化趋势的,虽然这是实际的点,由于曲线图多为展示一种趋势,所以这种图看起来很难看。于是我们需要对曲线进行光滑处理。

这里我们将用到一种插值方法,即样品spline插值法。大多数工具软件都提供样品的方式来光滑曲线。其实样条来源于实践,在很久以前进行工艺加工和造船时,为了减少接触阻力,往往要把接触面设计得很光滑,于是就用很有弹性的木条来作为参考(如下图),这样就可以用样条作为参考工具来做出光滑的曲线。 Continue reading »

 Posted by at 12:00 上午
8月 052010
 
If repeats are sweet, then the SAS Education e-Learning Technology team is running on a sugar high that would make Willy Wonka (and my young daughters) envious. Not only did it just earn honors from the Society for Technical Communication’s (STC) international competition for the second consecutive year; it took home the highest accolade possible: an Award of Distinguished Technical Communication, for the multimedia e-course SAS Programming 2: Data Manipulation Techniques.

In the e-learning world, that feat is like chasing an ice cream sundae with chocolate cake and a hearty sampling of sugar-coated Saturday-morning breakfast cereal. It doesn’t get much sweeter. The STC, a membership organization that dedicates itself to advancing the arts and sciences of technical communication, is the largest group of its kind in the world.

Last year, the e-course SAS Programming Introduction: Basic Concepts won STC’s Excellence Award, proving, as Vice President for Education Larry Stewart commented, that the e-learning team “continues to set the bar high for this type of technical communication.”

Translating the engaging style of a traditional classroom instructor to electronic form is certainly no easy task, but SAS Instructional Technology Manager Nancy Goodyear’s group designed an effective way to transport color, verve and functionality to even the grayest of cubicles with a dynamic computer course that uses audio, Flash movie and demos to present the training. STC judges were particularly impressed with the course’s “exceptional” organization and navigation and its ability to engage the learner through interactive questions, practices and quizzes.

Do you need more proof that the SAS e-Learning team is the cream of the crop? Nope, probably not. But here’s the cherry on top, all the same: To advance to the international competition, the course first had to distinguish itself from all other entries in the remarkably challenging STC Carolina Chapter Online Competition – which includes many Research Triangle Park peers. It did, winning top honors and Best of Show there.

Goodyear said we can expect more new e-courses in the near future, and that’s (dare we say it?) sweet news for SAS users who love the convenience of e-Learning. Have you taken a SAS e-course recently? Tell us what you liked about it.


8月 052010
 
One guy asked in a SAS forum about a typical table look up problem:
He has a data with two IDs:
id1 id2
a b
a e
b c
b e
c e
d e

and he wants to generate a new data set with the following structure according to above information :
id a b c d e
a 0 1 0 0 1
b 1 0 1 0 1
c 0 1 0 0 1
d 0 0 0 0 1
e 1 1 1 1 0

The real data is potentially big.
***************************;
At first look, this is a typical table look up problem SAS programmers facing almost everyday, that is duplicate keyed lookup table. It is a simple one because there is no inherent relationship among records.


data original;
   input id1 $ id2 $;
datalines;
a b
a e
b c
b e
c e
d e
;
run;

proc datasets library=work nolist;
     modify original;
  index create id1 id2;
quit;

proc sql;
     create table all_cases as
  select a.*, monotonic() as seq
  from (
  select distinct id1 as id
  from original
  union
  select distinct id2 as id
  from original
  ) as a
  order by a.id
  ;
quit;

proc sql noprint;
     select id into :idnames separated by ' '
  from   all_cases
  ;
quit;

data new;
  if _n_=1 then do;
     declare hash _h(dataset:'all_cases');
     _h.defineKey('id');
     _h.defineData('seq');
     _h.defineDone();
     end; 
     set all_cases;

  array _a{*} &idnames; 

  id1=id;  
  set original key=id1;      
  _mx_=%sysrc(_sok);
  
  do while (_iorc_=%sysrc(_sok));   
     rc=_h.find(key:id2); if rc=0 then _a[seq]=1;
  id1=id;
     set original key=id1;  
  
  end;
  _ERROR_=0;
  
  id2=id;  
  set original key=id2;      
  do while (_iorc_=%sysrc(_sok)); 
     rc=_h.find(key:id1); if rc=0 then _a[seq]=1;
  id2=id;
     set original key=id2;  
  end;
  _ERROR_=0;
  do j=1 to dim(_a); _a[j]=max(0, _a[j]); end;
  keep id &idnames;
run;

On the other hand, this problem can be solved in a more SASsy way like this:


data original;
   input id1 $ id2 $;
datalines;
a b
a e
b c
b e
c e
d e
;
run;

proc sql;
     create table newx as
     select a.id1, a.id2, (sum(a.id1=c.id1 & a.id2=c.id2)>0) as count
     from   
       (select a.id as id1, b.id as id2 
        from all_cases as a, all_cases as b) as a
left join   original as c
       on   a.id1=c.id1 or a.id2=c.id1
    group by a.id1, a.id2
    ;
quit;

proc transpose data=newx  out=_freq_t name=id2;
     by id1;
     var count;
     id id2;
run;

data _freq_t;
     set _freq_t;
     array _n{*} _numeric_;
     do i=1 to dim(_n);
        _n[i]=(_n[i]>0);
     end;
     drop i;
run;

proc transpose data=_freq_t(drop=id2) out=_freq_t2  name=id1;
     id id1;
run;

proc sql noprint;
     select id1, count(distinct id1) into :covars separated by ' ', :count
     from   _freq_t;  
quit;

data new2;
     set _freq_t;
     array _x{*} &covars;
     array _x2{&count} _temporary_;

     do j=1 to &count; _x2[j]=_x[j]; end;
     set _freq_t2;
     do j=1 to &count; _x[j]=(_x[j]+_x2[j]>0); end;
     drop j id2;
run;
 Posted by at 12:06 上午

Table Look Up in SAS, practical problems

 Data Manipulation, Hash Object, Index  Table Look Up in SAS, practical problems已关闭评论
8月 052010
 


One guy asked in a SAS forum about a typical table look up problem:
He has a data with two IDs:
id1 id2
a b
a e
b c
b e
c e
d e

and he wants to generate a new data set with the following structure according to above information :
id a b c d e
a 0 1 0 0 1
b 1 0 1 0 1
c 0 1 0 0 1
d 0 0 0 0 1
e 1 1 1 1 0

The real data is potentially big.
***************************;
At first look, this is a typical table look up problem SAS programmers facing almost everyday, that is duplicate keyed lookup table. It is a simple one because there is no inherent relationship among records.


data original;
   input id1 $ id2 $;
datalines;
a b
a e
b c
b e
c e
d e
;
run;

proc datasets library=work nolist;
     modify original;
  index create id1 id2;
quit;

proc sql;
     create table all_cases as
  select a.*, monotonic() as seq
  from (
  select distinct id1 as id
  from original
  union
  select distinct id2 as id
  from original
  ) as a
  order by a.id
  ;
quit;

proc sql noprint;
     select id into :idnames separated by ' '
  from   all_cases
  ;
quit;

data new;
  if _n_=1 then do;
     declare hash _h(dataset:'all_cases');
     _h.defineKey('id');
     _h.defineData('seq');
     _h.defineDone();
     end; 
     set all_cases;

  array _a{*} &idnames; 

  id1=id;  
  set original key=id1;      
  _mx_=%sysrc(_sok);
  
  do while (_iorc_=%sysrc(_sok));   
     rc=_h.find(key:id2); if rc=0 then _a[seq]=1;
  id1=id;
     set original key=id1;  
  
  end;
  _ERROR_=0;
  
  id2=id;  
  set original key=id2;      
  do while (_iorc_=%sysrc(_sok)); 
     rc=_h.find(key:id1); if rc=0 then _a[seq]=1;
  id2=id;
     set original key=id2;  
  end;
  _ERROR_=0;
  do j=1 to dim(_a); _a[j]=max(0, _a[j]); end;
  keep id &idnames;
run;

On the other hand, this problem can be solved in a more SASsy way like this:


data original;
   input id1 $ id2 $;
datalines;
a b
a e
b c
b e
c e
d e
;
run;

proc sql;
     create table newx as
     select a.id1, a.id2, (sum(a.id1=c.id1 & a.id2=c.id2)>0) as count
     from   
       (select a.id as id1, b.id as id2 
        from all_cases as a, all_cases as b) as a
left join   original as c
       on   a.id1=c.id1 or a.id2=c.id1
    group by a.id1, a.id2
    ;
quit;

proc transpose data=newx  out=_freq_t name=id2;
     by id1;
     var count;
     id id2;
run;

data _freq_t;
     set _freq_t;
     array _n{*} _numeric_;
     do i=1 to dim(_n);
        _n[i]=(_n[i]>0);
     end;
     drop i;
run;

proc transpose data=_freq_t(drop=id2) out=_freq_t2  name=id1;
     id id1;
run;

proc sql noprint;
     select id1, count(distinct id1) into :covars separated by ' ', :count
     from   _freq_t;  
quit;

data new2;
     set _freq_t;
     array _x{*} &covars;
     array _x2{&count} _temporary_;

     do j=1 to &count; _x2[j]=_x[j]; end;
     set _freq_t2;
     do j=1 to &count; _x[j]=(_x[j]+_x2[j]>0); end;
     drop j id2;
run;
 Posted by at 12:06 上午
8月 042010
 
It’s no secret that SAS enjoys a high degree of customer loyalty and it’s also well known that part of what drives that loyalty is driven by how much we pay attention to our customers.

This devotion to our customers is helping to ensure that we deliver on our promise of rock-solid solutions to business problems by giving customers the power to know more about their business issues, as well as how to address them. As per my previous post about branding being as much about operational alignment as it is about clear communications ("Are You All Paying Attention?"), I see a story here about the power of the SAS brand.

The many ways SAS pays attention to its customers begins with the fact that SAS customers receive a full suite of support services at no additional charge, including skilled telephone technical support and unlimited around-the-clock online technical support. And that’s just the tip of the iceberg:

  • The SAS Customer Support Site has more than 250,000 searchable resource pages on documentation, samples and SAS® notes that provide problem solutions as well as usage and installation information.
  • The SAS Technical Support service includes an average hold time of less than 30 seconds.
  • The SAS Technical Support staff has an average of 12 years of experience as statisticians, technical architects, programmers, database administrators and operating system engineers.
  • The SAS Education Division aims to provide customers with information before they need it through nearly 5,000 courses in any given year to over 60,000 students worldwide through a variety of media to accommodate multiple learning styles.
  • So far this year, the SAS Customer Loyalty Team contacted over 6.500 SAS representatives at SAS Customers in the U.S. alone.
  • More than 5,400 emails have been sent about the new SAS® Customer Resource Center, which has a wealth of information organized by the person’s role, including administrators, analysts, decision makers, programmers and statisticians.
  • SAS offers a library of videos to provide an overview of resources that customers have available to them, and a different link if reading about it is preferred.
  • The SAS Publications Division enables SAS customers to help other SAS customers by highlighting their own real-world ways to solve their business problems using SAS software.

All these resources begin and end with the customer in mind, which points to the degree to which SAS culture centers on the customer. [As I write that, I hear my marketing professor in my head voicing his approval.] To me, what’s even more notable is how many SAS User’s Groups there are around the world, and every single one of them is run entirely by our customers. Now that is loyalty!

[Special thanks to Kat Hardy for the original internal article on this topic and to Melissa Perez for helping me keep the details in this post accurate.]
8月 032010
 
We're taking a break from posting for most of August. We'll be back in a month with new examples, including R- and SAS-applicable tricks and tools.

Please drop us any ideas in the comments or by e-mail. We love feedback of any kind.

持续高温天气,大家纷纷表示很热 (从7月30日持续分析到8月5日)

 SAS 绘图, 世博, 仪表盘, 温度, 温湿指数, 舒适度  持续高温天气,大家纷纷表示很热 (从7月30日持续分析到8月5日)已关闭评论
8月 032010
 

子弹图(Bullet graph/chart)是由斯蒂芬(Stephen Few)从条形图演化而来。据称灵感来自温度计图和仪表盘中的进度条。子弹图提供了一个用于仪表盘可选图形。相对于表示KPI指标的常用仪表盘的gagues和meters,它只需很小的空间,简洁和提供更多的信息,在这里我用它在表示夏天天气的舒适程度。温湿指数是用温度和湿度为变量用来描述人对天气舒适程度的感觉指标。显然,像处于武汉,长沙,上海等南方城市,仅用温度这一指标来衡量天气是否适宜是不可靠的。如果全面考虑人对热环境的感受而言,影响因素很多,除了生理因素,气象因素包括温度、湿度、风速、风向、气压和辐射等等。但是考虑过多的因素使得指标复杂,难以实施使用。于是本博用易于得到的温度和湿度两个变量,使用温湿指数公式:THI= 温度-0.55*(1-相对湿度)*(温度-14.5)。其中温度采用摄氏温度,单位为摄氏度,相对湿度为干湿球温度计读得,单位为%。

上图数据测试地点是上海虹桥机场,时间是2010.08.03早上7:30,温度为33度,相对湿度为75%,THI达到30.5。 温湿指数THI反映了群体的人对环境的热感受。当夏季的THI小于21.1时,几乎无人有不舒适感;THI>=21.1时,随着THI的增大,具有不舒适感的人增多;THI达到23.9时,约有50%的人感到不舒适;THI达到26.6时,几乎无人感到舒适;特别是THI达到29.5时,酷热难忍。许多国家政府甚至将这一值作为工厂企业等停业下限指标(文献来自1981年)。       Continue reading »

 Posted by at 12:00 上午
8月 022010
 
Contributed by Scott Vodicka, a member of the SAS Global Consulting Business Intelligence Practice

The other day I needed to go to the SAS Customer Support Website and an article caught my eye. The title of the article is FAQ: How to make user-defined formats available in a SAS Business Intelligence deployment. So I think to myself... you know everytime I need to specify a custom SAS Format Catalog to a BI environment, I have to go look it up just to make sure to get it done right. I do not know why, but I do.

I will let you read the SAS Note to get all of the details, but here are a couple of points about what has changed for specifying user-defined format catalogs to your SAS BI Environment. As we all know, or in my case have to look up, you have to place your user-defined formats catalog named formats.sas7bcat in the SASFormats directory. (Your SASFormats directory should be located in a path similar to this
C:\SAS\Config\Lev1\SASApp\SASEnvironment\SASFormats.)
Next, update the sasv9_usermods.cfg (new in SAS 9.2) in your Application Server directory, which is in a path like this C:\SAS\Config\Lev1\SASApp, with the following lines to register your format catalog:

-set MyFmtLib "SASEnvironment/SASFormats"
-insert fmtsearch MyFmtLib

The insert statement is new to SAS 9.2.

The SAS Note goes on to explain how you can use a different name for your format catalog, and how you can use a different directory for your format catalog if you do not want to use the standard one in your SAS configuration. Oh, one more thing, the note also compares the SAS 9.2 methods to the SAS 9.1 methods, so if you are still using SAS 9.1 then this note will help you out too!

Thank you Technical Support for this helpful SAS Note!

Note: Scott has also contributed the post SAS gets your attention with a text message.
8月 022010
 
Link: http://support.sas.com/resources/papers/proceedings10/096-2010.pdf

在使用PROC FREQ執行卡方檢定時,如果看到列聯表下面出現warning的訊息,就表示這個列聯表有50%以上的期望值小於五,因此程式會建議使用Fisher's exact test。然後使用者必須回到程式裡面,在tables statement後面加上一個exact的選項,再重跑一次PROC FREQ才能得到Fisher's exact test的結果。Wei Xu於SAS GLOBAL FORUM 2010發表了一個macro程式,讓電腦自動幫使用者判斷要不要進行Fisher's exact test,若需要的話會順便把Fisher's exact test的結果跑出來,使用者不需再去重新執行PROC FREQ一次。



這個macro名叫%RUN_FISHERS,裡面只有四個參數須要設定:

  • Data= 要進行卡方檢定的資料名稱
  • Row= 放在行的變數名稱
  • Col= 放在列的變數名稱
  • Count= 如果資料是已經整理好的列聯資料,則會多一個計數變數來表示某一欄位的個數,此時需要把這個變數定義在這個參數裡面。如果不是列聯資料的話,可在此留空白。
範例:
 data test; 
   input r c ct; 
   datalines; 
   1 1 12 
   1 2 5 
   1 3 6 
   2 1 13 
   2 2 2 
   2 3 4 
   ; 
 run;   
%run_fishers(data=test, row=r, col=c, count=ct);
由於此資料會出現warning訊息,所以Fisher's exact test的結果就會直接顯示在報表最下方。如果今天資料變成:
data test; 
input r c ct; 
datalines; 
1 1 12 
1 2 50 
1 3 60 
2 1 13 
2 2 20 
2 3 40 

run;   
%run_fishers(data=test, row=r, col=c, count=ct);
報表最下方就不會出現Fisher's exact test的結果。

最後是這個macro的原始碼:
%macro run_fishers (version, data=, row=, col=, count=); 
%let _version=1.0; 
%if &version ne %then %put RUN_FISHERS macro Version &_version; 
%let opts = %sysfunc(getoption(notes))  
            _last_=%sysfunc(getoption(_last_)); 
%if &version ne debug %then %str(options nonotes;); 
 
/* Check for newer version */ 
%if %sysevalf(&sysver >= 8.2) %then %do; 
%let _notfound=0; 
 
filename ver url 'http://ftp.sas.com/techsup/download/stat/versions.dat' termstr=crlf; 
 data _null_; 
    infile ver end=_eof; 
    input name:$15. ver; 
    if upcase(name)="&sysmacroname" then do; 
       call symput("_newver",ver); stop; 
    end; 
 
 
    if _eof then call symput("_notfound",1); 
run; 
  %if &syserr ne 0 or &_notfound=1 %then 
    %put &sysmacroname: Unable to check for newer version; 
  %else %if %sysevalf(&_newver > &_version) %then %do; 
    %put &sysmacroname: A newer version of the &sysmacroname macro is available.; 
    %put %str(         ) You can get the newer version at this location:; 
    %put %str(         ) http://support.sas.com/ctx/samples/index.jsp; 
  %end; 
 %end; 
  
proc freq data=&data noprint; 
  %if &count ne %then %str(weight &count / zeros;); 
  tables &row*&col / sparse outexpect out=_out1; 
run; 
 
proc means data=_out1 noprint; 
  var count; 
  output out=_out2; 
run; 
 
data _null_; 
  set _out1; 
  if expected<=5 then warn+1; 
  if _n_=1 then set _out2; 
  pct_lt5=warn/_freq_; 
  if _freq_=_n_; 
  warning=(pct_lt5>=.2); 
  call symput('warning',warning); 
run; 
 
options &opts; 
 
proc freq data=_out1; 
  weight count / zeros; 
  tables &row*&col / chisq; 
  %if &warning=1 %then %do; 
  exact fisher; 
  %end; 
run; 
 
%mend; 

CONTACT INFORMATION 
Wei Xu
Boston Scientific
100 Boston Scientific Way
Marlborough, MA 01752-1234
(508) 683-4264
wei.xu@bsci.com