SAS/IML: как использовать отдельные компоненты дисперсии в RANDNORMAL

Это вопрос программирования, но сначала я расскажу вам немного о статистике. Этот вопрос относится к части моделирования данных для масштабной модели местоположения со смешанными эффектами (т. е. гетерогенных отклонений). Я пытаюсь смоделировать два компонента отклонения MVN, используя функцию RANDNORMAL в IML. Поскольку оба компонента дисперсии неоднородны, дисперсии, используемые методом RANDNORMAL, будут различаться у разных людей. Таким образом, мне нужно, чтобы IML выбрал конкретную строку (например, строка 1 = человек 1) и использовал функцию RANDNORMAL перед переходом к следующей строке и так далее.

Мой пример кода ниже предназначен для 2 человек. Я использую DO для циклического просмотра конкретных компонентов дисперсии каждого человека (VC1 и VC2). Я получаю сообщение об ошибке: «Модуль RANDNORMAL вызывается снова перед выходом из предыдущего вызова». Я предполагаю, что мне нужна какая-то функция BREAK или EXIT в цикле DO, но ни одна из них, которые я пробовал, не работает.

PROC IML;
    ColNames = {"ID" "VC1" "VC2"};
    A = {1 2 3, 
         2 8 9};
    PRINT A[COLNAME=ColNames];
    /*Set men of each variance component to 0*/ 
    MeanVector = {0, 0};
    /*Loop through each person's data using THEIR OWN variances*/
    DO i = 1 TO 2;
        VC1 = A[i,2];
        VC2 = A[i,3];
        CovMatrix = {VC1 0, 
                     0   VC2};
        CALL RANDSEED(1);  
        U = RANDNORMAL(2, MeanVector, CovMatrix);
    END;
QUIT;

Любая помощь приветствуется. О, и я использую SAS 9.4.


person Ryan W.    schedule 18.09.2014    source источник
comment
Вы генерируете всего 2 строки или 2 строки на человека? (Кроме того, если вы используете IML, используйте правильный тег — Рик отвечает на вопросы sas-iml, но я не знаю, смотрит ли он только на sas.)   -  person Joe    schedule 19.09.2014
comment
В каждом ряду один человек. О, и они не позволили бы использовать единственный тег IML, потому что у меня нет 1500 репутации...   -  person Ryan W.    schedule 19.09.2014
comment
Это потому, что это sas-iml.   -  person Joe    schedule 19.09.2014
comment
Ха! Да, я понял это минуты 3 назад.   -  person Ryan W.    schedule 19.09.2014


Ответы (2)


Вы хотите переместить некоторые вещи, но в основном вы не хотите переписывать U дважды: вам нужно написать 1-ю строку U, затем 2-ю строку U, если я понимаю, что вы пытаетесь сделать. Приведенное ниже также немного более эффективно, поскольку я j() матрицы U и _cv, а не строю, а затем заново каждый раз через цикл (что медленно).

proc iml;

  a = {1 2 3,2 8 9};
  print(a);
  _mv = {0,0};
  U = J(2,2);
  _cv = J(2,2,0);
  CALL RANDSEED(1);   

  do i = 1 to 2;
    _cv[1,1] = a[i,2];
    _cv[2,2] = a[i,3];
    U[i,] = randnormal(1,_mv, _cv);
  end;
  print(u);
quit;
person Joe    schedule 18.09.2014
comment
Этот ответ полностью правильный и отлично сработал. С учетом сказанного, мой пример кода был запрограммирован примерно так, как, по моему мнению, должны выглядеть шаги в IML, поэтому приведенное ниже исправление кода Рика сохранило для меня это соответствие (требуется меньше умственных усилий). Ваше решение неизбежно будет очень полезным для других. Спасибо! - person Ryan W.; 19.09.2014
comment
Я настоятельно рекомендую прочитать другие сообщения в блоге Рика — у него есть несколько хороших примеров того, как следует делать определенные вещи, в том числе почему следует использовать j() как я делаю выше, а не регенерировать их, как вы делаете каждый раз. (Но на самом деле я не программист IML, поэтому мой ответ в значительной степени основан на этом прочтении!) - person Joe; 19.09.2014
comment
После сравнения обоих решений и увеличения числа людей до 1000 я обнаружил, что ваш код намного эффективнее. Это не вина Рика, это моя собственная дерьмовая программа. Мне просто потребовалось некоторое время, чтобы понять, что именно ты делаешь. Я переключаюсь между галочками ответов, потому что хочу выбрать оба ответа, поскольку они приводят меня к одному и тому же месту. В любом случае, я очень ценю это! Еще раз спасибо за ваше терпение. - person Ryan W.; 19.09.2014

Ваша ошибка - линия

CovMatrix = {VC1 0, 0   VC2}; /* wrong */

который не является допустимым синтаксисом SAS/IML. Вместо этого используйте подход @Joe или используйте

 CovMatrix = (VC1 || 0) // (0 || VC2);

Подробнее см. в статье "Как строить матрицы из выражений."

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

person Rick    schedule 19.09.2014
comment
Это здорово, спасибо, Рик! Ваш первый связанный пост в блоге отлично объясняет, что я сделал неправильно. Честно говоря, я просто не мог достаточно хорошо сформулировать свой вопрос в любом поиске Google, чтобы добраться до этого сообщения в блоге. Раньше я использовал фигурные скобки только для матриц, но я понятия не имел, что фигурные скобки хороши только для фиксированных значений (э-э, литералов). - person Ryan W.; 19.09.2014