SAS编程:如何确定变量最大小数位数以及应用?

2022-05-06  本文已影响0人  野藤_

(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的小数位数保留到宏变量中,直接在宏中进行引用。

整个过程处理如下:

 
上一篇 下一篇

猜你喜欢

热点阅读