이번 편에서는 PSPP에 없는 절차를 일부러 던져 봅니다. 앞의 편들이 “SPSS에서 하던 이 분석이 PSPP에서도 똑같이 된다”를 보여 드렸다면, 이번 편은 반대로 “여기서부터는 갈린다”를 보여 드리는 편입니다.
살펴볼 것은 세 가지입니다. 첫째, 없는 절차를 실행하면 PSPP가 어떤 오류를 내는지. 둘째, 그 오류 메시지가 정확히 무엇이 없다고 말해 주는지. 셋째, 같은 질문에 PSPP로 답할 수 있는 우회로가 있는지입니다. PSPP로 옮겨 갈지 고민하시는 분께는 이 편이 가장 실용적인 판단 자료가 될 것입니다. 되는 것보다 안 되는 것을 미리 알아야 중간에 막히지 않으니까요.
데이터
이번에도 data/training_survey.sav를 씁니다. 여기에 반복측정 설계(사전·사후 × 집단), 혼합모형, 편상관, Chart Builder 그래프, 그리고 SPSS 전용 고급 절차 열두 가지를 차례로 시도해 봅니다.
반복측정 설계라는 말이 낯선 분을 위해 짧게 설명하면, 같은 사람을 여러 번 측정한 자료를 말합니다. 이 예제에서는 한 사람마다 교육 전 점수(pre_score)와 교육 후 점수(post_score)가 있고, 그 사람이 실험군인지 대조군인지(group)가 있습니다. “시점에 따라 점수가 변했는가”, “그 변화가 집단마다 다른가”를 묻는 설계입니다.
메뉴에서 먼저 보인다
사실 신택스를 돌려 보기 전에 메뉴만 봐도 차이가 드러납니다. 1편에서 본 PSPPIRE의 Analyze 메뉴에는 General Linear Model 항목 자체가 없습니다. SPSS 32의 같은 메뉴를 펼치면 일변량, 다변량, 반복측도, 분산성분이 나란히 있는 것과 대조됩니다.


메뉴에 없는 것은 신택스로 직접 입력해도 실행되지 않습니다. PSPP의 메뉴는 결국 신택스를 만들어 주는 창구이기 때문입니다. 다만 신택스로 실행해 보면 한 가지 얻는 것이 있습니다. 오류 메시지가 무엇이 없는지를 꽤 정확하게 말해 준다는 점입니다. 그래서 이번 편은 메뉴 대신 신택스로 진행합니다.
신택스로 던져 보기
사용하는 파일은 syntax/10_unsupported_glm_repeated.sps, 11_unsupported_mixed.sps, 13_unsupported_graphs.sps의 GGRAPH 부분, 14_data_mgmt_extra_procs.sps의 PARTIAL CORR 부분입니다. 네 가지 모두 SPSS에서는 정상적으로 실행되는 신택스라는 점을 기억해 두세요. PSPP에서 오류가 나는 것은 신택스를 잘못 써서가 아니라 PSPP에 그 기능이 없어서입니다.
* 반복측정 GLM: 사전·사후 점수를 종속변수 두 개로 넣고 집단(group)을 개체 간 요인으로 둔다.
* WSFACTOR=time 2 는 개체 내 요인 time 이 2수준(사전, 사후)이라는 뜻이다.
* SSTYPE(3) 은 제3유형 제곱합, WSDESIGN 과 DESIGN 은 개체 내·개체 간 모형이다.
GLM pre_score post_score BY group
/WSFACTOR=time 2 Polynomial
/METHOD=SSTYPE(3)
/WSDESIGN=time
/DESIGN=group.
* 선형 혼합모형: 사전 점수를 공변량으로 통제하고 집단 효과를 본다.
* RANDOM 줄은 부서(dept)마다 절편이 다를 수 있다는 변량효과, REML 은 추정 방법이다.
MIXED post_score BY group WITH pre_score
/FIXED=group pre_score
/RANDOM=INTERCEPT | SUBJECT(dept)
/METHOD=REML.
* 편상관: 학력(edu)의 영향을 뺀 연봉과 나이의 상관.
PARTIAL CORR
/VARIABLES=salary age BY edu
/SIGNIFICANCE=TWOTAIL.
* Chart Builder 그래프: GGRAPH 로 그래프용 데이터를 정의하고 GPL 블록에서 모양을 그린다.
* GPL 블록 내용은 길어서 생략했다. 전체는 13_unsupported_graphs.sps 에 있다.
GGRAPH
/GRAPHDATASET NAME="gd" VARIABLES=dept MEAN(salary)[name="ms"]
/GRAPHSPEC SOURCE=INLINE.
BEGIN GPL
...
END GPL.
이 네 덩어리를 PSPP에서 실행하면 다음과 같은 답이 돌아옵니다.
syntax/10_unsupported_glm_repeated.sps:5.5-5.24: error: GLM: Multivariate analysis is not yet
implemented.
5 | GLM pre_score post_score BY group
| ^~~~~~~~~~~~~~~~~~~~
syntax/11_unsupported_mixed.sps:4.1-4.5: error: MIXED: MIXED is not yet implemented.
4 | MIXED post_score BY group WITH pre_score
| ^~~~~
error: PARTIAL CORR: PARTIAL CORR is not yet implemented.
error: GGRAPH: GGRAPH is not yet implemented.
error: Unknown command `BEGIN GPL'.
메시지를 하나씩 읽어 보겠습니다. 맨 앞의 syntax/10_unsupported_glm_repeated.sps:5.5-5.24는 “이 파일의 5번째 줄, 5번째 글자부터 24번째 글자까지가 문제”라는 위치 표시입니다. 그 아래 ^~~~ 표시(캐럿)가 해당 위치에 밑줄을 그어 줍니다. MIXED, PARTIAL CORR, GGRAPH는 모두 “not yet implemented”, 즉 아직 구현되지 않았다는 뜻입니다. 마지막 줄의 BEGIN GPL은 조금 다릅니다. GGRAPH가 실패하면서 PSPP가 그 뒤의 GPL 블록을 독립된 명령으로 읽으려 했고, 그런 명령은 모른다고 답한 것입니다.
여기서 눈여겨볼 곳은 첫 번째 메시지의 캐럿 위치입니다. 캐럿이 /WSFACTOR가 아니라 종속변수 두 개 pre_score post_score를 가리키고 있습니다. 즉 PSPP가 막히는 지점은 반복측정이라는 설계가 아니라 종속변수가 여러 개라는 것 자체입니다. 실제로 /WSFACTOR 없이 종속변수만 둘 넣은 MANOVA도 정확히 같은 메시지를 냅니다. PSPP의 GLM은 종속변수가 하나인 일변량 분석까지만 지원한다고 이해하시면 됩니다. 7편에서 돌린 단변량 GLM(상호작용 포함)이 정상 작동했던 것도 그 때문입니다.
SPSS 전용 절차 열두 가지
syntax/15_spss_only.sps에는 PSPP에 아예 없을 것으로 예상한 절차를 모아 두었습니다. 다항·순서형 로지스틱, 일반화 선형모형, MANOVA, 생존분석(Kaplan-Meier, Cox), 판별분석, 계층적 군집, 복합표본, 시계열(ARIMA, 전문가 모델러), R·Python 연동입니다. 논문이나 실무 분석에서 “SPSS 고급 기능”이라고 부를 만한 것들이지요.
결과는 분명했습니다. SPSS 32에서는 전부 돌아갔고, PSPP에서는 한 절차도 돌지 않았습니다. 흥미로운 것은 PSPP가 내는 오류가 두 종류로 나뉜다는 점입니다.
| PSPP의 반응 | 명령 |
|---|---|
not yet implemented (명령은 알지만 미구현) |
NOMREG, PLUM, KM, COXREG, DISCRIMINANT, CLUSTER, CSPLAN, CSDESCRIPTIVES, DATE, TSMODEL |
Unknown command (명령 자체를 모름) |
GENLIN, ARIMA, BEGIN PROGRAM |
10번과 같은 Multivariate analysis is not yet implemented |
GLM 종속변수 2개 (MANOVA) |
두 메시지의 차이는 이렇습니다. “not yet implemented”는 PSPP가 그 명령의 이름은 알고 있고 개발 목록에도 올라 있지만 아직 기능이 채워지지 않았다는 뜻입니다. 반면 “Unknown command”는 명령어 표에 그 이름조차 없다는 뜻입니다. 앞으로의 가능성에는 차이가 있겠지만, 지금 당장 쓸 수 없다는 점에서는 어느 쪽이든 같습니다.
한 가지 꼭 주의하셔야 할 것이 있습니다. PSPP는 BEGIN PROGRAM 블록 안의 Python 코드를 신택스로 읽으려고 합니다. 그래서 import sys 같은 줄을 IMPORT 명령으로 해석해 오류를 내고, 곧바로 “연쇄 실패를 막기 위해 처리를 중단한다”며 파일 실행을 멈춥니다. 다른 오류들은 해당 명령만 건너뛰고 다음 명령으로 넘어가는데, 이 경우는 파일 전체가 거기서 끝나 버립니다. 신택스 파일 중간에 Python 블록이 있으면 그 뒤에 있는 명령은 하나도 실행되지 않는다는 뜻입니다. SPSS에서 쓰던 신택스 파일을 PSPP로 가져올 때 BEGIN PROGRAM 블록부터 걷어내야 하는 이유가 여기 있습니다.
SPSS에서는 어떻게 나오나
비교를 위해 같은 신택스를 SPSS 32에서 돌린 값을 정리했습니다. 표에서 PSPP 열이 비어 있는 것이 바로 이번 편의 요점입니다.
| 절차 | SPSS 32 | PSPP 2.1.1 |
|---|---|---|
| 반복측정 GLM: time F (1, 198) | 113.962, p<.001 | — |
| 반복측정 GLM: time × group F | 80.272, p<.001 | — |
| MIXED: group F (1, 197) | 81.014, p<.001 (비수렴 경고) | — |
| PARTIAL CORR: 학력 통제 연봉–나이 r | .628, df=197, p<.001 | — |
| MANOVA: group Wilks λ / F | .700 / 42.281 (2, 197) | — |
| GGRAPH 막대그래프 | 정상 (한글 축 레이블 포함) | — |
MIXED 줄의 비수렴 경고가 걱정되실 수 있는데, 이것은 SPSS가 잘못된 것이 아닙니다. 예제 데이터를 만들 때 부서별 차이를 넣지 않았기 때문에, 부서 변량효과의 분산이 0으로 추정되면서 반복 계산이 깔끔하게 끝나지 않은 것입니다. 통계적으로는 “이 변량효과는 필요 없어 보인다”는 정상적인 안내로 읽으시면 됩니다.
아래 우회로에서 이 표의 숫자 두 개(time × group F 80.272, 편상관 .628)를 PSPP로 다시 만들어 보겠습니다.
우회로
반복측정 2수준 설계 → 차이 점수의 t-검정
사전·사후 두 시점과 집단 하나로 이루어진 설계에서 연구자가 궁금한 것은 대개 시점×집단 상호작용입니다. 풀어 말하면 “실험군의 점수 변화가 대조군의 변화보다 큰가”입니다.
이 질문은 사실 반복측정 GLM 없이도 답할 수 있습니다. 한 사람마다 차이 점수(gain = 사후 − 사전)를 계산한 다음, 그 차이 점수를 두 집단 사이에서 독립표본 t-검정으로 비교하면 됩니다. 시점이 두 개뿐일 때는 이 두 검정이 수학적으로 같은 검정입니다.
이 t-검정은 4편에서 이미 돌렸습니다. 그때 얻은 t=-8.959를 제곱하면 80.26이고, SPSS 반복측정 GLM의 time×group F는 80.272입니다. 자유도도 (1, 198)로 같습니다. 분자 자유도가 1인 F는 t의 제곱과 같다는 관계가 있어서, 반올림 범위 안에서 같은 값이 나온 것입니다. 표의 숫자를 PSPP로 재현한 셈입니다.
다만 이 우회로는 시점이 두 개일 때만 통합니다. 시점이 셋 이상이거나 개체 내 요인이 둘 이상이면 차이 점수 하나로 요약할 수 없기 때문입니다. 그런 설계라면 R(afex, lme4 패키지)이나 jamovi·JASP로 가셔야 합니다.
편상관 → 회귀 잔차의 상관
편상관은 “제3의 변수 영향을 빼고 본 두 변수의 상관”입니다. 정의로 들어가면 “통제변수로 각각 회귀한 뒤 남은 잔차끼리의 상관”과 같습니다. 이 예제에서는 연봉을 학력으로 설명하고 남은 부분, 나이를 학력으로 설명하고 남은 부분을 구해 두 나머지끼리 상관을 보면 됩니다.
PSPP의 REGRESSION은 잔차를 새 변수로 저장할 수 있으니, 세 줄이면 편상관을 직접 계산할 수 있습니다. 저장소의 syntax/chk_partial_corr_workaround.sps입니다.
* 1단계: 연봉을 학력으로 회귀하고 잔차를 저장한다. 새 변수 RES1 이 생긴다.
REGRESSION /DEPENDENT salary /METHOD=ENTER edu /SAVE=RESID.
* 2단계: 나이를 학력으로 회귀하고 잔차를 저장한다. 새 변수 RES2 가 생긴다.
REGRESSION /DEPENDENT age /METHOD=ENTER edu /SAVE=RESID.
* 3단계: 두 잔차의 상관이 곧 학력을 통제한 연봉–나이 편상관이다.
CORRELATIONS /VARIABLES=RES1 RES2 /PRINT=TWOTAIL SIG.
|RES1 Pearson Correlation|1.000| .628|
| Sig. (2-tailed) | | .000|
출력에서 RES1 행과 RES2 열이 만나는 칸의 .628이 편상관 계수입니다. 옆의 1.000은 RES1과 자기 자신의 상관이라 의미가 없습니다. SPSS의 PARTIAL CORR 값 .628과 소수 셋째 자리까지 같습니다.
SPSS와 다른 점은 하나뿐입니다. SPSS에서는 /SAVE=RESID(이름)처럼 저장할 변수 이름을 지정할 수 있지만, PSPP의 /SAVE=RESID는 이름을 지정하지 못하고 RES1, RES2처럼 순서대로 자동 이름이 붙습니다. 그래서 3단계에서 RES1, RES2라는 이름을 그대로 쓴 것입니다.
한 가지 짚어 둘 점이 있습니다. 이 방법으로 얻는 상관 계수는 정확히 같지만, 옆에 나오는 유의확률은 CORRELATIONS가 일반 상관으로 계산한 값입니다. 편상관의 자유도는 통제변수 수만큼 줄어들어야 하므로(SPSS 표의 df=197), 유의성을 엄밀하게 보고해야 한다면 이 차이를 감안하셔야 합니다. 이 예제처럼 r이 크고 표본이 200명이면 결론은 달라지지 않습니다.
나머지
위 두 가지 말고는 PSPP 안에서 해결할 방법이 마땅치 않습니다. 절차별로 정리하면 다음과 같습니다.
- MANOVA, 혼합모형, 생존분석, 판별분석, 시계열: PSPP 안에는 우회로가 없습니다. R을 쓰시는 것이 가장 확실합니다. 코드 작성이 부담스럽다면 jamovi나 JASP가 GUI로 MANOVA와 혼합모형을 지원합니다.
- 다항·순서형 로지스틱: 범주가 셋이면 이항 로지스틱을 범주 쌍마다 따로 돌리는 편법이 있긴 하지만, 엄밀히 같은 모형은 아닙니다. R의 nnet, MASS 패키지를 쓰시는 편이 낫습니다.
- GGRAPH: PSPP의 GRAPH 명령으로 히스토그램·산점도·막대그래프까지는 그릴 수 있습니다(3편의 상자그림처럼 png로 나옵니다). 발표 자료처럼 꾸밈이 필요하다면 9편에서처럼 결과를 csv로 뽑아 다른 도구에서 그리시면 됩니다.
- Python·R 연동: PSPP에는 없습니다. 대신 PSPP를 배치 모드로 돌리고 출력을 csv로 받아 Python이나 R에서 이어서 처리하는 방식이 있고, 이것이 9편에서 다룰 흐름입니다.
정리하면, 기초부터 중급까지의 분석은 PSPP로 충분하지만 여러 종속변수를 한꺼번에 다루는 분석, 개체 안의 상관 구조를 모형화하는 분석, 그리고 특수 분야 절차로 넘어가면 다른 도구가 필요합니다. 옮겨 가기 전에 자신이 자주 쓰는 절차가 위 표에 있는지 먼저 확인해 보시기 바랍니다.
다음 편
9편에서는 이 시리즈의 모든 PSPP 출력을 GUI 없이 만든 방법, 즉 배치 실행과 자동화를 다룹니다. 이번 편에서 PSPP의 빈자리를 보셨다면, 다음 편에서는 PSPP가 SPSS보다 나은 지점을 보시게 될 것입니다.
시리즈 목차: 0편 총론 · 1편 · 2편 · 3편 · 4편 · 5편 · 6편 · 7편 · 8편 안 되는 것과 우회로 · 9편