(PS:文章只写了一半,留作项目讨论用,讨论部分在2.1节)
在临床项目试验中,会生成数值变量的描述性统计量的Table。各个统计量的小数位数的确定,不同的公司、不同的项目可能有不同的要求。
有的,要求统计量展示固定的小数位数;有的,要求统计量小数位数根据原数据小数位数确定。
前者,直接固定统计量格式进行输出,无需特殊的处理;后者,需要获取原始数据的小数位数,进而判断输出统计量的保留位数后,进行输出。
这篇文章介绍一下,后者的处理和应用过程。
1. 小数位数确定
原始数据小数位数的确定,一般有2个来源:
第一,从保存在SPEC中的数值格式确定数据的小数位数;
第二,直接从数据集中获取数据的最大小数位数。
1.1 SPEC中的格式
SPEC中,会规定输出变量的格式,数值变量的小数位数可以从格式中获取。
SPEC信息一般保存在EXCEL中,导入SAS数据集不复杂,有的公司直接把SPEC的信息保存在特定的逻辑库中。
我以P21的SPEC为例,项目中SPEC的内容与这个类似:
P21从SPEC中,可以获取到参数的名称、参数结果的数据类型、有效小数位数。程序中,稍加整理,不复杂就可以获得以下内容的数据集。
**Import SPEC:
options validvarname = v7;
proc import datafile="XXX_p21e_adam.xlsx" out = vlm1
dbms = xlsx replace;
getnames = yes;
sheet = "ValueLevel";
run;
**Get decimal information;
data vlm;
set vlm1;
where dataset = "ADLB" and data_type = "float";
length paramcd $8;
paramcd = scan(where_clause, 4, ".");
decimal = significant_digits;
keep dataset paramcd decimal;
run;
ADLB Decimal
1.2 从原始数据集获取小数位数
我用一个ADLB数据集进行演示:
ADLB整个思路是,将每个Paramcd的数值检测值以best.
格式Put出来,以小数点.
右侧字符的长度作为该值的小数位数,取变量值中最大的小数位数值。
这里有一个注意点,整数Put出来的字符是没有小数点.
的,所以需要单独判断。
libname test "E:\99_Test";
proc sql noprint;
create table decimal as
select distinct paramcd,
max(case
when index(strip(put(aval,best.)), ".")= 0 then 0
else length(scan(strip(put(aval,best.)), 2, "."))
end) as decimal
from test.adlb
where aval ne .
group by paramcd;
quit;
ADLB Decimal
2.小数位数确定之后,如何应用?
描述性统计量的小数位数,一般的要求是:n保留整数;Max、Min与原数据小数位数一致;Mean、Median比源数据多保留1位小数;SD比源数据多保留2位小数。同时,统计量展示的最大小数位数一般不超过4位。
具体如何展示,还需要看项目中的要求,并不固定。这篇文章,以上面的要求来进行举例。
2.1 小数位数的基础应用
最基础的小数位数应用,是使用SAS的put
语句,常用的方法是直接Put具体的数字格式。不过,这中处理方式在负数十分位向0进位时,可能会产生一些偏误。
我用代码进行实例,对数字0.4, 0.5, -0.4, -0.49 -0.5
四舍五入保留整数。使用两种方法,一种是直接put数值格式8.0
;一种是使用函数Round处理之后,再put数值格式8.0
。
data tmp;
input a @@;
bput = strip(put(a, 8.0));
bround = strip(put(round(a, 1), 8.0));
datalines;
0.4
0.5
-0.4
-0.49
-0.5
;
run;
Result 1
从结果中可以看到,对于-0.4
和-0.49
这2个数值,四舍五入应该进位成0
,但是直接Put时,结果是-0
,与想要的结果不同。更一般的,对于(-0.5, 0)
这个范围的数,Put保留整数时,结果为-0
。
我没细究这个现象的原因,建议大家在保留小数位数时,先使用Round
函数,再put
相应的格式。两个函数保留的小数位数要相同,否则会产生二次误差。
2.2 单个Paramter的统计量的小数位数处理
数值变量统计量的小数位数处理,受到如何处理所有参数的影响。
以ADLB举例,分析数据集有多个数值型结果的参数。这里有两种处理方式,第一,一次对一个参数进行统计输出,其他参数依次重复;第二,将Paramter作为分组变量,一次处理所有需要分析的参数结果。
对应的,小数位数保留的处理也因此不同。
先先计算出数值变量的统计量:
**Create formats for output;
**Get statitstics;
proc means data = test.adlb noprint nway;
by trt01an ;
where paramcd = "APTT" and aval ne .;
var aval;
output out = stats1 n = n_ mean = mean_ std = sd_ median = median_ min = min_ max=max_;
run;
stat1
从从面可以知道,参数的APTT的小数位数为1,按照规则,小数位数处理如下:
data stats2;
length n mean sd median min max $50;
set stats1;
n =strip(put(n_, best.));
mean =strip(put(round(mean_, 0.1**(1+1) ), 8.2));
sd =strip(put(round(sd_, 0.1**(1+2) ), 8.3));
median =strip(put(round(median_, 0.1**(1+1) ), 8.2));
min =strip(put(round(min_, 0.1**(1+0) ), 8.1));
max =strip(put(round(max_, 0.1**(1+0) ), 8.1));
run;
stats2
工作中,我们不能直接用1来代入,这样就是Hard Coding了。我们可以将APTT的小数位数保留到宏变量中,直接在宏中进行引用。
整个过程处理如下:
网友评论