按组和块划分的箱线图,具有轴对齐的统计数据
Boxplot by groups & blocks, with axis-aligned statistics
我一直在按组和时间点块为箱线图构建 GTL 模板。我怀疑SAS 9.4(TS Level 1M2)中的GTL还没有完全支持这种多维、轴对齐的BOXPLOT加BLOCKPLOT组合。
- 如果我错了,我将不胜感激有关正确方法的建议。
- 如果我是对的,我欢迎提出或多或少简单的 GTL 解决方法的建议。
下面的代码产生了第一个情节,但我真的想要第二个情节。换句话说,我希望 BLOCKPLOT 支持与 BOXPLOT(时间点和治疗组)相同的两个 x 轴水平。但是,BLOCKPLOT 只会在 X 轴(时间点)内堆叠 CLASS(治疗组)。但是 BOXPLOT 将在块内沿 X 轴分隔组。
我找不到任何方法可以从 BLOCKPLOT 的 "stack" 方法切换到像 BOXPLOT 这样的 "cluster" 方法。 (我也尝试过 AXISTABLE,但它们的行为类似于 BLOCKPLOT。)
感谢您指出正确的方法或建议解决方法。
我已经看过的代表性讨论:
SOF:SAS GRAPH: align axis for 2 plots with lattice rows
来自 9.4 (TS1M2) 代码的绘图,如下所示:
我想编码的明显操纵的情节:
第一个图的代码:
/* 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;
至少这个核心是可以回答的。如果您使用 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
使颜色与您的线条颜色匹配,尽管没有(much/any)控制背景填充。
我一直在按组和时间点块为箱线图构建 GTL 模板。我怀疑SAS 9.4(TS Level 1M2)中的GTL还没有完全支持这种多维、轴对齐的BOXPLOT加BLOCKPLOT组合。
- 如果我错了,我将不胜感激有关正确方法的建议。
- 如果我是对的,我欢迎提出或多或少简单的 GTL 解决方法的建议。
下面的代码产生了第一个情节,但我真的想要第二个情节。换句话说,我希望 BLOCKPLOT 支持与 BOXPLOT(时间点和治疗组)相同的两个 x 轴水平。但是,BLOCKPLOT 只会在 X 轴(时间点)内堆叠 CLASS(治疗组)。但是 BOXPLOT 将在块内沿 X 轴分隔组。
我找不到任何方法可以从 BLOCKPLOT 的 "stack" 方法切换到像 BOXPLOT 这样的 "cluster" 方法。 (我也尝试过 AXISTABLE,但它们的行为类似于 BLOCKPLOT。)
感谢您指出正确的方法或建议解决方法。
我已经看过的代表性讨论:
SOF:SAS GRAPH: align axis for 2 plots with lattice rows
来自 9.4 (TS1M2) 代码的绘图,如下所示:
我想编码的明显操纵的情节:
第一个图的代码:
/* 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;
至少这个核心是可以回答的。如果您使用 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
使颜色与您的线条颜色匹配,尽管没有(much/any)控制背景填充。