按组和块绘制箱线图,使用轴对齐统计数据。

3
我一直在为分组和时间点块的箱线图建立GTL模板。我怀疑SAS 9.4(TS Level 1M2)中的GTL尚未完全支持这样多维、轴对齐的BOXPLOT加BLOCKPLOT组合。
  • 如果我错了,我很希望得到正确方法的建议。
  • 如果我是对的,我欢迎提出一个相对简单的GTL解决方案的建议。
下面的代码生成第一个图,但我真正想要的是第二个图。换句话说,我希望BLOCKPLOT支持与BOXPLOT相同的两个x轴级别(时间点和治疗组)。然而,BLOCKPLOT只会在X轴(时间点)内对CLASS(治疗组)进行堆叠。但是,BOXPLOT将在块内沿着X轴分开GROUPs。
我没有找到任何切换从BLOCKPLOT的“堆叠”方法到像BOXPLOT那样的“cluster”方法的方式。(我也尝试过AXISTABLEs,但它们的行为类似于BLOCKPLOT。)
感谢指出正确的方法或提供解决方法。
我已经看过的代表性讨论:

以下是来自9.4(TS1M2)代码的绘图: 来自9.4(TS1M2)代码的绘图

显然被处理过的情节,我想编写代码:
我想从GTL获得的明显被处理过的情节
第一个情节的代码:
/* Set up test data structure, with few seed observations */
  proc sql;
    create table labstruct
      (  mygroup         char(3) label='Treatment Group'
       , myvisitnum      num     label='Visit number'
       , myvisitname     char(8) label='Visit name'
       , labtestname     char(8) label='Name of lab test'
       , labseed         num     label='Lab measurement seed'
       , lablow          num     label='Low end of normal range'
       , labhigh         num     label='High end of normal range'
      )
    ;
    insert into labstruct
      values('A', 1,  'Day 1',  'Test XYZ', 48, 40, 60)
      values('B', 1,  'Day 1',  'Test XYZ', 52, 40, 60)
      values('A', 5,  'Week 1', 'Test XYZ', 50, 40, 60)
      values('B', 5,  'Week 1', 'Test XYZ', 50, 40, 60)
      values('A', 10, 'Week 2', 'Test XYZ', 52, 40, 60)
      values('B', 10, 'Week 2', 'Test XYZ', 48, 40, 60)
    ;
  quit;

  /* Make more obs from the seeds above */
    data labdata;
      set labstruct;

      do repeat = 1 to 20;
        labvalue = labseed + 6*rannor(3297);
        if ranuni(59843)>0.1 then output;
      end;

      label labvalue = 'Lab measurement';
      drop repeat labseed;
    run;


/* Calculate summary stats, and merge onto lab data for use as "block" labels */
  proc summary data=labdata noprint;
    by myvisitnum mygroup;
    var labvalue;
    output out=labstats (drop=_type_) 
           n=n mean=mean std=std;
  run;

  /* Merge summary stats onto lab data, used in GTL template as "block" labels */
  data labdata;
    merge labdata (in=in_data)
          labstats (in=in_stats);
    by myvisitnum mygroup;
    label n      = 'n'
          mean   = 'Mean'
          std    = 'Std Dev';
  run;


proc template;
  define statgraph xalignedstats;
    dynamic _TRT _AVISIT _AVISITN _AVAL _STAT1 _STAT2 _STAT3;

    begingraph / border=false dataskin=none attrpriority=none;

      layout overlay / walldisplay=none ;

        innermargin / align=top separator=false pad=(top=0);
          blockplot x=_AVISITN block=_AVISIT /
                    display=(outline values) valuefitpolicy=split ;
        endinnermargin;

        boxplot x=_AVISITN y=_AVAL /
                group=_TRT groupdisplay=cluster clusterwidth=0.8 ;

        innermargin / align=bottom separator=false pad=(bottom=0);
          blockplot x=_AVISITN block=_TRT / class=_TRT label='Treatment' filltype=alternate;
          blockplot x=_AVISITN block=_STAT1 / class=_TRT label='n' filltype=alternate;
          blockplot x=_AVISITN block=_STAT2 / class=_TRT label='Mean' filltype=alternate;
          blockplot x=_AVISITN block=_STAT3 / class=_TRT label='Std Dev' filltype=alternate;
        endinnermargin;

      endlayout;

    endgraph;
  end;
run;

proc sgrender data=labdata template=xalignedstats;
  dynamic 
          _TRT     ='mygroup'
          _AVISITN ='myvisitnum' 
          _AVISIT  ='myvisitname' 
          _AVAL    ='labvalue'
          _STAT1   ='n'
          _STAT2   ='mean'
          _STAT3   ='std'
          ;
run;

1
如果您在communities.sas.com上发布,SAS图形专家Sanjay或DanH通常会回复。但考虑到日期,您可能得不到太多帮助。 - Reeza
1
SAS和Sanjay不会让你失望 - 即使在这个时候(http://blogs.sas.com/content/graphicallyspeaking/2015/12/23/box-plot-with-stat-table-and-markers/)。 - Dante
1个回答

2

至少这个核心问题是可以回答的。如果你使用axistable而不是blockplot,你可以选择指定classdisplay=cluster,它的作用类似于groupdisplay=cluster(为什么名称不同,我也不知道)。

proc template;
  define statgraph xalignedstats;
    dynamic _TRT _AVISIT _AVISITN _AVAL _STAT1 _STAT2 _STAT3;

    begingraph / border=false dataskin=none attrpriority=none;

      layout overlay / walldisplay=none ;

        innermargin / align=top separator=false pad=(top=0);
          blockplot x=_AVISITN block=_AVISIT /
                    display=(outline values) valuefitpolicy=split ;
        endinnermargin;

        boxplot x=_AVISITN y=_AVAL /
                group=_TRT groupdisplay=cluster clusterwidth=0.8 ;

        innermargin / align=bottom separator=false pad=(bottom=0);
          axistable x=_AVISITN value=_TRT / class=_TRT label='Treatment' classdisplay=cluster colorgroup=_TRT;
          axistable x=_AVISITN value=_STAT1 / class=_TRT label='n'  classdisplay=cluster colorgroup=_TRT;
          axistable x=_AVISITN value=_STAT2 / class=_TRT label='Mean' classdisplay=cluster colorgroup=_TRT;
          axistable x=_AVISITN value=_STAT3 / class=_TRT label='Std Dev' classdisplay=cluster colorgroup=_TRT;
        endinnermargin;

      endlayout;

    endgraph;
  end;
run;

你可能会更难(或不可能)完全正确地排版,例如交替颜色,但这至少是一个开始。例如,你可以考虑使用colorgroup来使颜色与线条颜色匹配,尽管无法控制背景填充。


1
非常感谢,乔。我在axistable上错过了classdisplay选项。GTL功能强大且广泛。 - Dante

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接