【问题标题】:Bring the length of an array to another array in SAS?将数组的长度带到SAS中的另一个数组?
【发布时间】:2015-07-01 08:24:04
【问题描述】:

我有一个很大的 SAS 表,让我们将列描述为字符格式的 A 和 B 列,所有其他列都可以采用数字格式(每个变量都有不同的名称),长度未知,例如:

A     B   Name1    Name2    Name3 ....    NameN
-------------------------------------------------
Char Char Number1  Number2  Number3 ..... NumberN
.................................................
.................................................

目标是数值数组 Name1-NameN 将通过 Class=B (By B) 向下求和, 所以决赛桌会是这样的:

 A     B   Name1 Name2 Name3 ....  NameN
----------------------------------------
Char Char  Sum1  Sum2  Sum3 .....  SumN
........................................
........................................

为了做这个总结,我描述了 2 个数组。第一个是:

array Varr {*} _numeric_; /* it reads only numerical columns */

然后我描述了另一个长度相同的数组(Summ1-SummN)来做求和过程。

问题是我只能手动描述这个新数组的长度。例如,如果有 80 个数值,那么我必须手动编写如下:

array summ {80} Summ1-Summ80; 

代码在我手动编写时有效。但相反,我想写一些类似

array summ {&N} Summ1-Summ&N;  /* &N is the dimension of the array Varr */

我尝试在数组下使用 do-loop 和 dim(Varr) 以多种不同的方式,例如:

data want;
array Varr {*} _numeric_;
do i=1 to dim(Varr);
    N+1 ; 
end;
%put &N; 
array Summ {&N} Summ1-Summ&N;
retain Summ;

if first.B then do i=1 to dim(varr); summ(i)=varr(i) ;end;  
else do i =1 to dim(varr); summ(i) = summ(i) + varr(i) ; varr(i)=summ(i);  end; 

drop Summ1-Summ&N;
run;

但它不起作用。关于如何将第一个数组的长度带到第二个数组的任何想法?

【问题讨论】:

  • 嗯,如果我理解你的问题是正确的,N 是一个数据步变量,&N 调用一个宏变量,所以你必须使用 call symput('N',N);循环后或更好:调用 symput('varrLen',dim(Varr));并删除循环(不确定 n 是否从全局宏变量中保留)
  • 现在我在循环后都尝试了 call symput('N',N);并在循环内调用 symput('varrLen',dim(Varr));对于以下代码,两者都给出了相同的错误:array Summ {*} Summ1-Summ&N;错误是:“编号变量列表 (Summ1-SummN) 上缺少数字后缀。”
  • 我猜你必须使用 summ"&N" ,但我不确定你是否可以通过这种方式生成变量名。最好先尝试 Keiths 解决方案

标签: arrays sas


【解决方案1】:

您需要在上一步中计算并存储数值变量的数量。最简单的方法是使用dictionary.columns 元数据表,在proc sql 中可用。这包含给定数据集的所有列详细信息,包括类型(num 或 char),因此您只需计算类型为“num”的列数。

下面的代码就是这样做的,并将结果存储在一个宏变量 &N 中。使用into : 功能。我还使用了leftput这两个函数来删除宏变量中的前导空格,否则你在放summ1-summ&N.时会遇到问题

我还根据您的回答添加了第二个解决方案,但效率更高,因为它不读取任何记录,只读取列详细信息

proc sql noprint;
select left(put(count(*),best12.)) into :N
from dictionary.columns
where libname='SASHELP' and memname='CLASS' and type='num';
quit;

%put Numeric variables = &N.;

/*****************************************/
/* alternative solution */

data _null_;
set sashelp.class (obs=0);
array temp{*} _numeric_;
call symputx('N',dim(temp));
run;

%put Numeric variables = &N.;

【讨论】:

  • 我在主表之后使用了您的proc sql 代码,但它给出了N=3 而不是N=87(应该是87)。我正在考虑是否我写错了任何参数。我检查了表格属性:type='Number',所以我成功了。我也想知道memname,是我的表名吗? (在这种情况下,它是一个保存在work库中的临时表)
  • @user3714330 我以数据集sashelp.class 为例。您需要将 libnamememname 更改为您正在使用的任何库和数据集
【解决方案2】:

现在我找到了另一个解决方案,对 @kl78 的解决方案稍作修改

在我尝试使用call symput ('N',dim(varr)); 之前,我忘记更改数字格式并删除不必要的空格。当我在没有格式的情况下运行它时,代码试图找到Summ_____87,所以它给出了错误。

现在我用call symput ('N',put(dim(varr),2.));格式运行,代码可以找到Summ87,所以现在完全成功了。

【讨论】:

  • call symputx 也将修剪空格,而无需 put 语句(在您的情况下,仅当变量数量在 10 到 99 之间时才有效)
  • 我已经按照你的思路为我的答案添加了第二个解决方案,但通过不读取数据集记录来提高效率
猜你喜欢
  • 2018-08-04
  • 1970-01-01
  • 2019-04-07
  • 1970-01-01
  • 2020-07-13
  • 2017-01-24
  • 1970-01-01
  • 2021-03-18
  • 2023-03-12
相关资源
最近更新 更多