Цикл по параллельным спискам / массивам в макросе SPSS - PullRequest
1 голос
/ 09 марта 2020

Я хотел бы написать макрос SPSS для выполнения трех операций:

  1. создать пользовательскую таблицу,
  2. очистить окно вывода,
  3. таблица экспорта.

Как вы знаете, средство макросов SPSS позволяет использовать два типа циклов: «numberri c» like (!do !i = !x !to !y) и «list» / «для каждого« like (!do !i !in (!1)) , Моя цель - создать макрос с вызовом, как показано ниже: col v1 v2 / "Sheet A" "Sheet B"., работающий таким образом (с «списком», подобным l oop):

  1. Получить имя первой переменной (v1)
  2. Поместите его в макрос ctables
  3. Получить имя первого листа (строка "Лист A")
  4. Поместите его в макрос output export
  5. Получить имя второй переменной
  6. ...
  7. Получить имя второго листа
  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".

Вывод был в целом неверным, потому что я получал таблицы только со второй переменной. Однако в файле я нашел два листа с правильными именами. Итак, я попытался вложить:

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 пересекает каждый элемент из списка с левой стороны от '/', а каждый элемент из списка с правой стороны от '/ и перезаписывает предыдущие результаты в файле Excel. Моя цель - получить расширения макросов, например:

* 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 списка по 2 элемента, но только два цикла, а не четыре. У кого-нибудь есть идеи, как получить такой результат?

1 Ответ

1 голос
/ 09 марта 2020

Насколько мне известно, не существует формального / прямого способа запуска al oop в параллельных списках в макросе SPSS, поэтому вы можете выбрать - либо go Python, либо найти обходной путь - вот несколько идей:

1. Воссоздайте оба списка, используя число l oop
, так что вы l oop на числах скажете от 1 до 5, и используйте их для создания имен переменных - от v1 до v5 и от «листа 1» до «листа» 5 ":

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

Вы также можете добавить начальные и \ или конечные числа к вызову макроса, если они не являются константами.
Это, конечно, будет работать, только если два ваших списка имеют общий нумерация как в примере выше. Если они этого не делают, вы можете использовать один из следующих вариантов:

2. L oop по одному списку при «проглатывании» второго
Макрос SPSS l oop выполняет итерации только по одному списку за раз - но вместо итерации по второму списку вы можете взять элемент и удаляйте его из второго списка для каждой итерации первого списка:

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. Определите макрос для одной пары, используйте несколько вызовов макросов Это самый простой способ, если у вас есть только несколько элементов в каждом списке. Вы можете определить макрос с одним именем переменной и одним именем листа. Вы сможете получить те же результаты, выполнив -

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

вместо col VARa VARb/ "sheet 1" "sheet 2" . Как вы пытались раньше.

Если эти списки длинные, вы можете автоматизировать запуск макросов отдельно (например, используя команду write - но это для отдельного вопроса).

...