在 SPSS 宏中循环并行 lists/arrays

Looping through parallel lists/arrays in an SPSS macro

我想编写一个 SPSS 宏来执行三个操作:

  1. 生成自定义 table,
  2. 清理输出 window,
  3. 导出 table.

如您所知,SPSS 宏工具允许使用两种类型的循环:'numeric' like (!do !i = !x !to !y) 和 'list'/'for each' like (!do !i !in (!1)).我的目标是创建一个调用如下的宏: col v1 v2 / "Sheet A" "Sheet B". 以这种方式工作(使用 'list' 循环):

  1. 获取第一个变量名 (v1)
  2. 放在ctables宏部分
  3. 获取第一个sheet名字(字符串"Sheet A")
  4. 放在output export宏部分
  5. 获取第二个变量名
  6. ...
  7. 获得第二个sheet名字
  8. ...

等等。

一开始我是这样写的:

define col (!positional !charend('/')
/!positional !cmdend)

!do !i !in (!1)

output close all.

  ctables
  /table x1 + x2
  by !i [mean f1.2, totals[mean f1.2]].

  output modify
  /select logs headings texts warnings pagetitles outlineheaders notes
  /deleteobject delete = yes.

!doend

!do !i !in (!2)

   output export
    /contents export = visible
    /xlsx documentfile = "E:\path\file.xlsx"
      operation = createsheet
      sheet = !i.

!doend

!enddefine.

*** MACRO CALL.
col v1 v2 / "Sheet A" "Sheet B".

输出总体上是不正确的,因为我只用第二个变量得到了 tables。但是,在文件中我发现了两个名称正确的 sheet。所以,我尝试嵌套:

define col (!positional !charend('/')
/!positional !cmdend)

!do !i !in (!1)
!do !j !in (!2)

output close all.

  ctables
  /table x1 + x2
  by !i [mean f1.2, totals[mean f1.2]].

  output modify
  /select logs headings texts warnings pagetitles outlineheaders notes
  /deleteobject delete = yes.

   output export
    /contents export = visible
    /xlsx documentfile = "E:\path\file.xlsx"
      operation = createsheet
      sheet = !j.

!doend
!doend

!enddefine.

*** MACRO CALL.
col v1 v2 / "Sheet A" "Sheet B".

输出完全相同,这意味着 SPSS 将“/”左侧列表中的每个元素与“/”右侧列表中的每个元素交叉,并覆盖 [=64= 中的先前结果] 文件。我的目标是接收这样的宏扩展:

* FIRST EXPANSION:
...
  ctables
  /table x1 + x2
  by v1 [mean f1.2, totals[mean f1.2]].
...
   output export
    /contents export = visible
    /xlsx documentfile = "E:\path\file.xlsx"
      operation = createsheet
      sheet = "Sheet A".

* SECOND (LAST) EXPANSION:
...
  ctables
  /table x1 + x2
  by v2 [mean f1.2, totals[mean f1.2]].
...
   output export
    /contents export = visible
    /xlsx documentfile = "E:\path\file.xlsx"
      operation = createsheet
      sheet = "Sheet B".

换句话说 - 2 列出 x 2 个元素但只有两个循环 - 而不是四个。有谁知道如何得到这样的结果吗?

据我所知,没有 formal/direct 方法可以 运行 在 SPSS 宏中的并行列表上循环,所以你的选择是 - 要么去 Python,要么找到解决方法 - 这里有一些想法:

1.使用数字循环重新创建两个列表
所以你在数字上循环说 1 到 5,并使用它们来创建变量名 - v1 到 v5 和 "sheet 1" 到 "sheet 5":

!do !i=1 !to 5
.....
  by !concat("v",!i) [mean f1.2, totals[mean f1.2]].
.....
  sheet = !quote(!concat("sheet ",!i))
.....
!doend

您还可以将开始 and\or 结束数字添加到宏调用中(如果它们不是常量)。
这当然只有在您的两个列表共享一个公共编号时才有效,如上例所示。如果他们不这样做,您可以使用以下方法之一:

2。循环遍历一个列表,而 "eating through" 第二个
SPSS 宏循环一次只遍历一个列表 - 但不是遍历第二个列表,您可以在第一个列表的每次迭代中获取一个项目并将其从第二个列表中删除:

define col (!pos !charend('/') / !pos !cmdend)
!let !arr2=!2
!do !i !in(!1)
    .....
    by !i [mean f1.2, totals[mean f1.2]].
    .....
!let !sheet=!head(!arr2)
!let !arr2=!tail(!arr2)
    .....
    sheet = !sheet
    .....
!doend
!enddefine.

*and the macro call:
col VARa VARb VARc/"sheet 1" "sheet 2" "sheet 3".

3。在单个对上定义宏,使用多个宏调用 这是最简单的方法,如果每个列表中只有几个项目 - 您可以使用单个变量名称和单个 sheet 名称定义宏,您将能够通过 运行宁 -

col VARa/ "sheet 1" .
col VARb/ "sheet 2" .

而不是 col VARa VARb/ "sheet 1" "sheet 2" .,就像您之前尝试的那样。

如果这些列表很长,您可以自动执行 运行 单独调用宏(例如使用 write 命令 - 但这是一个单独的问题)。