【问题标题】:SAS - Reference One Dimension of a Multi-Dimension ArraySAS - 参考多维数组的一维
【发布时间】:2015-12-15 17:27:08
【问题描述】:

我有一个宏,它接受一维数组作为参数。我想将二维数组的一维传递给它,但我不知道如何干净地引用二维数组的一维来生成一个新的一维数组。我确定我缺少一些明显的东西,但我找不到它。

以下是我编写的一些测试代码,用于尝试引用“myVals”的一维。

data test;
   array myVals {3,4} myVal1_1 - myVal1_4
                      myVal2_1 - myVal2_4
                      myVal3_1 - myVal3_4;
   do i = 1 to 3;
      do j = 1 to 4;
         myVals{i,j} = j - i + 3;
      end;
   end;

   array newArray {*} myVals{1}; *All of these throw errors;
   array newArray {*} myVals[1];
   array newArray {*} myVals(1);
   array newArray {*} myVals{1,};

   len2ndDim = dim2(myVals); *this produces a column with value 4;

   array newArray {len2ndDim}; *this throws error for "len2ndDim" not being an integer constant or *;
run;

编辑汤姆的评论 我希望能够创建一个命名数组 newArray,根据数据步循环变量是 1,2 还是 3,它可以别名为:

  • 变量 myval1_1 - myVal1_4 或
  • 变量 myVal2_1 - myVal2_4 或
  • 变量 myVal3_1 - myVal3_4

然后我会调用 myMacro,它需要三个参数 - 名称、开始索引、结束索引。我会这样打电话:

  • myMacro(newArray, 1, myEndIndex1) 或
  • myMacro(newArray, 1, myEndIndex2)

【问题讨论】:

  • 为什么?请记住,ARRAY 语句只是定义了一个别名,您可以使用它来引用多个变量,它实际上并没有创建一个数组数据结构。
  • 嗨,Tom,我想要一个别名,用于将二维数组的某个维度传递给接受一维数组的宏。
  • 您当前如何将数组作为参数传递?你如何看待通过一维?您的意思是要传递一个数字并将该数字解释为数组维度之一的索引吗?如果是这样,为什么不在 DATA 步骤代码中的数组引用中引用宏变量? myvals[&dim1,K]
  • 我有像上面的 myVal1_1 到 myVal3_4 这样的变量。我有一个来自 1-3 的 N 数据步循环(我定义的二维数组的第一个维度),对于每个 N 1,2 和 3,我想调用一个宏传递 ..N_1, ...N_2, 。 ..N_3 和 ...N_4 到一个宏。该宏接受数组的名称和开始/结束索引。因此,如果我可以从二维数组的第 N 维中创建一个新的数组别名,我可以将该数组名称传递给这个宏。传递 myvals[&dim1,K] 一次传递一个值,但我想传递一个可以对许多变量执行逻辑的数组名称。
  • 你能举个例子吗?我没有看到宏参数与您希望宏生成的数据步骤代码有何关联。如果我想将多个值传递给宏,那么我通常将其作为空格分隔列表来执行。因此,如果我有一个名为LIST 的参数,我可以使用LIST=1 3 6 7 调用宏。然后我可以使用%sysfunc(countw(&list)) 找出4 值已通过。

标签: arrays multidimensional-array sas


【解决方案1】:

假设您要选择包含 4 个值的 3 个维度之一,您可以像这样引用它:

array newArray [*] myVal2: ;

这是因为您的原始数组语句正在创建名为 myVal2_1, ... myVal2_4 的变量。上面的语句所做的只是使用通配符语法将每个以 'myVal2' 开头的变量放入一个新数组中。

如果您的数组具有更复杂的名称,则此方法将不起作用。您需要寻求更复杂的解决方案。

【讨论】:

  • 您好罗伯特,感谢您的及时回复。在我的实际用例中,我需要 myVal1: 或 myVal2: 或 myVal3: 取决于我循环通过 1-3 的 datastep var 的值(我的第一级维度)。所以我想我可以使用你的解决方案,但前提是我将循环变量更改为宏变量,这样我就会有类似 myVal&loopVar.: 的东西。尽管我需要该循环变量在其他地方成为 datastep var。我会继续思考的。再次感谢。
  • 如果你想定义在运行时之前维度未知的数组对象,你可以使用散列对象。如果您详细说明您想要什么和需要什么,我或其他人可能会提供帮助。
  • @MaxPower 是的 - 您需要根据您的描述对后缀进行宏化。或者,如果性能是一个因素,那么哈希对象将是数据 null 建议的更好方法。
  • 所以...使用 call symput() 将我的 datastep 循环变量移动到宏变量对我不起作用。在调用 symput 创建它(在程序执行时)之前,我遇到了调用宏 var(在宏执行时)的旧错误。为了解决这个问题,我通常会创建一个新的数据步骤来调用创建的宏变量。但在这种情况下,这不起作用,因为在新的数据步骤中,我丢失了所有数组分配。现在阅读散列对象。
  • 尾声...调用符号是不必要的。只是将 do 循环更改为 %do 循环。如果可能,我仍然更喜欢使用数据步进变量而不是宏变量,但这是可行的。
【解决方案2】:

我仍然不明白问题到底出在哪里。 如果您希望灵活地生成 ARRAY 语句,例如:

array myVals {3,4} myVal1_1 myVal1_4 myVal2_1-myVal2_4 myVal3_1 myVal3_4;

那你要使用三个参数:

%macro my2dmacro (basename=,dim1=,dim2=);
   %local i ;
array &basename.s {&dim1,&dim2}
    %do i=1 %to &dim1; &basename.&i._1-&basename.&i._&dim2 %end;
;
%mend my2dmacro;

那么如果你用这些值来调用它:

%my2dmacro(basename=myval,dim1=3,dim2=4);

它会生成这个语句:

array myvals {3,4} myval1_1-myval1_4 myval2_1-myval2_4 myval3_1-myval3_4;

当您想要请求一维数组时,您可以改用如下内容:

%macro my1dmacro (basename=,dim1=,dim2=);
array &basename.&dim1.s {&dim2} &basename.&dim1._1-&basename.&dim1._&dim2;
%mend my1dmacro;

如果你用这些值调用它:

%my1dmacro(basename=myval,dim1=3,dim2=4);

它会生成这个语句。

array myval3s {4} myval3_1-myval3_4;

您可以将它们组合成一个宏并使用另一个参数来允许用户指定要生成哪种形式的 ARRAY 语句。

【讨论】:

    【解决方案3】:

    DIM2 功能解决了我的问题。我想干净地引用二维数组的一维而不使用宏 %do 循环来循环变量名(如罗伯特彭里奇的答案中的 cmets 中所讨论的)。以下是如何使用 DIM2 仅引用 datastep vars。

    data test;
       array myVals {3,4} myVal1_1 - myVal1_4
                          myVal2_1 - myVal2_4
                          myVal3_1 - myVal3_4;
    
       array slice {4} slice_1 - slice_4;
    
       do i = 1 to 3;
           do j = 1 to DIM2{myVals};
              slice{j} = myVals{i,j}; 
              %do_calculations_on(input1Darray=slice, inputArrayLength=4}
           end;
       end;
    run;
    

    上述方法还允许通过颠倒 i,j 循环的顺序来对另一个维度进行切片

    array diff_slice {3} diff_slice1 - diff_slice3;
    do j = 1 to 4;
       do i = 1 to DIM1{myVals}; *DIM1 is DIM, or 3 in this case;
          diff_slice{i} = myVals{i, j}
          %do_calculations_on_(input1Darray=diff_slice, inputArrayLength=3);
       end;
    end;
    

    正如人们之前提到的,“传递数组”给我的宏实际上只是意味着传递一个字符串,该字符串表示变量列表的公共前缀。尽管如此,上面的方法允许我定义一组新的常用前缀变量来传递(slice 或 diff_slice),它们表示多维数组的任何维度的任何切片,使用数据步长变量,而不必依赖宏 do 循环以及以某种方式组织的初始数组名称。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-01-22
      • 1970-01-01
      • 1970-01-01
      • 2021-05-30
      • 2014-01-13
      • 2011-01-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多