이번 편에서는 분석 자체보다 분석 앞뒤에 필요한 작업들을 다룹니다. 실제로 데이터를 분석하다 보면 통계 절차를 돌리는 시간보다 데이터를 고르고, 나누고, 붙이는 시간이 더 길 때가 많습니다.
구체적으로는 이런 작업들입니다. 일부 케이스만 골라서 분석하기, 가중치 걸기, 집단별로 나눠서 돌리기, 집계값을 각 케이스에 붙이기, 다른 파일과 병합하기, 그리고 반복 작업을 줄여 주는 매크로입니다. 덤으로 단변량 GLM, K-평균 군집, ROC 곡선이 PSPP에서 돌아가는지도 확인합니다.
이번 편에는 PSPP에만 있는 함정이 하나 나옵니다. 오류 메시지 없이 틀린 값이 나오는 종류라서, 이 편에서 가장 중요한 부분이라고 생각합니다.
데이터
이번에도 data/training_survey.sav를 씁니다. 이 편의 신택스는 메모리에 열려 있는 활성 데이터를 바꾸지만, 마지막에 저장하지는 않습니다. 그래서 여러 번 돌려도 원본 파일은 그대로 남아 있습니다.
메뉴로 하기
Data 메뉴에 Select Cases, Weight Cases, Split File, Aggregate, Sort Cases가 있습니다. SPSS와 같은 자리이므로 SPSS를 써 보셨다면 바로 찾으실 수 있습니다.
Select Cases 대화상자에서는 무작위 표본 추출, 케이스 번호 범위 지정, 필터 변수 사용을 할 수 있습니다. 선택되지 않은 케이스를 분석에서 잠시 빼 두기만 할지, 아예 삭제할지도 여기서 정합니다.
다만 SPSS에 있는 “조건을 만족하는 케이스” 항목은 PSPP의 이 대화상자에 없습니다. SPSS에서 group = 2 같은 조건식을 입력해 케이스를 고르던 분이라면 당황하실 수 있습니다. 조건으로 고르려면 두 가지 방법이 있습니다. 아래 신택스의 SELECT IF를 쓰거나, Transform > Compute로 조건에 맞으면 1, 아니면 0인 변수를 만든 다음 그 변수를 필터 변수로 지정하는 것입니다.

신택스로 하기
syntax/14_data_mgmt_extra_procs.sps에서 데이터 관리 부분만 가져왔습니다. 명령마다 효과가 얼마나 오래 유지되는지가 다르다는 점을 눈여겨보세요. 다음 절차 하나에만 적용되는 것, 끌 때까지 유지되는 것, 데이터를 영구히 바꾸는 것이 섞여 있습니다.
* TEMPORARY + SELECT IF — 다음 절차 하나에만 실험군 선택.
* TEMPORARY 뒤의 변경은 바로 다음 절차 하나에만 적용되고 그 뒤에는 원래대로 돌아갑니다.
* TEMPORARY 없이 SELECT IF만 쓰면 선택되지 않은 케이스가 활성 데이터에서 아예 지워집니다.
TEMPORARY.
SELECT IF (group = 2).
DESCRIPTIVES VARIABLES=gain /STATISTICS=MEAN STDDEV.
* FILTER — 재수강 의향자만 (끌 때까지 유지).
* reenroll 값이 0이 아닌 케이스만 분석에 쓰고 나머지는 지우지 않고 제외만 합니다.
FILTER BY reenroll.
FREQUENCIES VARIABLES=dept /STATISTICS=NONE.
* FILTER OFF로 꺼야 이후 분석에 전체 케이스가 다시 들어갑니다.
FILTER OFF.
* WEIGHT — 여성 1.5배 가중.
* (gender = 2)는 참이면 1, 거짓이면 0이므로 여성은 w가 1.5, 남성은 1이 됩니다.
COMPUTE w = 1 + (gender = 2) * 0.5.
WEIGHT BY w.
FREQUENCIES VARIABLES=gender /STATISTICS=NONE.
WEIGHT OFF.
* SPLIT FILE — 집단별 분리 출력.
* SPLIT FILE은 같은 집단이 연속해 있어야 하므로 먼저 그 변수로 정렬합니다.
SORT CASES BY group.
SPLIT FILE BY group.
DESCRIPTIVES VARIABLES=pre_score post_score /STATISTICS=MEAN STDDEV.
SPLIT FILE OFF.
* AGGREGATE(ADDVARIABLES) — 부서별 평균 연봉을 각 케이스에 붙임.
* PSPP에서는 이 정렬이 반드시 필요하며 이유는 아래 함정 절에서 설명합니다.
SORT CASES BY dept.
* BREAK는 묶는 기준 변수, 그 아래 줄은 새 변수 이름과 계산 방법입니다.
AGGREGATE /OUTFILE=* MODE=ADDVARIABLES
/BREAK=dept
/dept_salary_mean=MEAN(salary) /dept_n=N.
* AGGREGATE(파일) + MATCH FILES — 조회 테이블 병합.
* 먼저 부서별 평균 향상분을 부서당 한 줄짜리 파일로 저장합니다.
AGGREGATE /OUTFILE='data/tmp_dept_agg.sav'
/BREAK=dept
/dept_gain_mean=MEAN(gain).
* MATCH FILES의 BY 변수로 병합하려면 양쪽 모두 그 변수로 정렬돼 있어야 합니다.
SORT CASES BY dept.
* FILE=*는 지금 열려 있는 데이터, TABLE은 부서별 값을 찾아 붙일 조회용 파일입니다.
MATCH FILES /FILE=* /TABLE='data/tmp_dept_agg.sav' /BY dept.
마지막의 AGGREGATE + MATCH FILES 조합은 엑셀의 VLOOKUP과 비슷한 일을 합니다. 부서별 요약표를 따로 만든 다음, 각 케이스의 부서를 보고 해당 값을 찾아 붙이는 것입니다.
INSERT FILE='다른파일.sps'로 외부 신택스 파일을 끼워 넣는 것도 됩니다. 자주 쓰는 변수 계산을 별도 파일로 빼 두고 여러 신택스에서 불러 쓰는 식으로 활용할 수 있습니다. 이 파일도 실제로 보조 신택스 syntax/inc_compute_ratio.sps를 INSERT로 불러와서 사후/사전 점수 비(score_ratio)라는 파생 변수를 만듭니다.
출력 읽기
명령마다 기대한 케이스만 들어갔는지를 N으로 확인하는 것이 핵심입니다.
- SELECT IF 뒤의 기술통계는 N=106으로, 실험군만 들어갔습니다. 평균 향상분은 8.27입니다.
- FILTER 뒤의 부서 빈도는 합계 87명으로, 재수강 의향자만 집계됐습니다.
- 가중치를 걸면 성별 빈도가 남성 99.00, 여성 151.50이 됩니다. 여성 케이스 하나하나가 1.5명으로 계산됐기 때문에 빈도에 소수가 붙습니다.
SPLIT FILE을 걸면 집단마다 “Split Values” 표가 먼저 나오고, 그 아래에 해당 집단의 결과가 따로 나옵니다.
Split Values
+---------+------+
|Variable | Value|
+---------+------+
|실험 집단|대조군|
+---------+------+
이 표는 “바로 아래 결과는 실험 집단 변수가 대조군인 케이스들의 것”이라는 머리표입니다. 출력이 길어지면 지금 보고 있는 표가 어느 집단 것인지 헷갈리기 쉬우니, 이 표를 기준으로 구간을 나눠 읽으시면 됩니다. 이어서 실험군의 Split Values 표와 결과가 한 번 더 나옵니다.
AGGREGATE로 붙인 부서별 평균 연봉은 3406.63(영업)에서 3944.36(개발) 사이의 세 값이고, 부서별 케이스 수는 42, 75, 83입니다. 각 케이스에 자기 부서의 값이 붙기 때문에, 200개 케이스 전체를 보면 이 세 값만 반복해서 나타납니다.
AGGREGATE 함정 — 정렬부터
이 부분은 실제로 겪은 일입니다. 부서별 케이스 수를 각 케이스에 붙이는, 아주 흔한 코드를 정렬 없이 돌렸습니다.
* 정렬(SORT CASES) 없이 돌린 코드이며 PSPP에서는 틀린 값이 나옵니다.
AGGREGATE /OUTFILE=* MODE=ADDVARIABLES
/BREAK=dept
/dept_n=N.
SPSS 32는 정렬 없이 돌려도 42 / 75 / 83으로 맞게 나옵니다. 그런데 PSPP는 오류 없이 틀린 값을 냅니다. 붙인 변수의 기술통계를 보면 바로 드러납니다.
+--------------------+---+----+-------+-------+
| | N |Mean|Minimum|Maximum|
+--------------------+---+----+-------+-------+
|dept_n |200|2.10| 1| 7|
Minimum과 Maximum 칸을 보세요. 부서는 세 개이고 각 부서의 인원은 42~83명인데, 부서별 케이스 수가 1에서 7 사이로 나왔습니다. 평균도 2.10밖에 되지 않습니다.
원인은 PSPP 매뉴얼에 적혀 있습니다. “ADDVARIABLES는 PRESORTED를 함의한다”는 문장입니다. PRESORTED는 “데이터가 이미 BREAK 변수 순서로 정렬돼 있다”고 가정하라는 옵션입니다. 그래서 PSPP는 데이터를 위에서부터 읽으면서 같은 부서가 연달아 이어지는 구간만 한 묶음으로 봅니다. 정렬되지 않은 데이터에서는 부서가 뒤섞여 있으니, 같은 부서가 몇 명씩 짧게 이어지는 구간마다 따로 세게 되고, 그 결과가 1~7이라는 작은 값입니다.
해결 방법은 간단합니다. 앞의 신택스처럼 SORT CASES BY dept.를 먼저 실행하면 SPSS와 같은 값이 나옵니다. SPSS용으로 짠 신택스를 PSPP로 옮길 때는 MODE=ADDVARIABLES를 검색해서 앞에 정렬이 있는지 꼭 확인하시길 권합니다. 오류가 나지 않기 때문에 오히려 더 위험한 함정입니다.
매크로
“PSPP는 매크로가 안 된다”는 말이 인터넷에 돌아다니는데, 지금은 맞지 않는 옛 정보입니다. syntax/12_unsupported_macro.sps에 넣어 둔 네 가지가 전부 돌아갑니다. 단순 매크로, 리스트 반복, 조건 분기, 숫자 반복과 변수 이름 조합입니다.
매크로는 신택스 안에서 쓰는 일종의 함수라고 생각하시면 됩니다. DEFINE과 !ENDDEFINE 사이에 틀을 정의해 두고, 매크로 이름을 부를 때 넘긴 값이 !vars 같은 자리에 끼워져 실행됩니다. 주석은 매크로 본문 안이 아니라 DEFINE 앞에 달아 두었습니다.
* 1) 단순 매크로: vars에 받은 변수 목록으로 기술통계를 냅니다.
* CMDEND는 명령 끝(마침표)까지를 전부 인자로 받는다는 뜻입니다.
DEFINE !desc(vars=!CMDEND)
DESCRIPTIVES VARIABLES=!vars /STATISTICS=MEAN STDDEV.
!ENDDEFINE.
!desc vars=age salary.
* 2) 리스트 반복: 받은 변수를 하나씩 꺼내 변수마다 빈도표를 따로 냅니다.
DEFINE !freqs(vars=!CMDEND)
!DO !v !IN (!vars)
FREQUENCIES VARIABLES=!v /STATISTICS=NONE.
!DOEND
!ENDDEFINE.
!freqs vars=gender dept.
* 3) 조건 분기: full이 1이면 통계량 네 개, 아니면 평균만 냅니다.
* TOKENS(1)은 인자로 단어 하나를 받는다는 뜻입니다.
DEFINE !desc2(var=!TOKENS(1) / full=!TOKENS(1))
!IF (!full = 1) !THEN
DESCRIPTIVES VARIABLES=!var /STATISTICS=MEAN STDDEV MIN MAX.
!ELSE
DESCRIPTIVES VARIABLES=!var /STATISTICS=MEAN.
!IFEND
!ENDDEFINE.
!desc2 var=age full=1.
!desc2 var=salary full=0.
* 4) 숫자 반복과 이름 조합: 1부터 n까지 돌며 q와 숫자를 붙여 q1, q2 같은 변수 이름을 만듭니다.
DEFINE !qfreq(n=!TOKENS(1))
!DO !i = 1 !TO !n
FREQUENCIES VARIABLES=!CONCAT(q, !i) /STATISTICS=NONE.
!DOEND
!ENDDEFINE.
!qfreq n=2.
실행 결과를 보면 !desc2 var=age full=1은 평균, 표준편차, 최솟값, 최댓값 네 통계량을 내고, full=0은 평균만 냅니다. !qfreq n=2는 q1과 q2의 빈도표를 냅니다. SPSS 32에서도 같은 표가 나왔습니다.
문항이 수십 개인 설문에서 네 번째 형태처럼 번호로 변수 이름을 만들어 반복하면, 같은 명령을 수십 줄 복사해 붙이지 않아도 됩니다.
단변량 GLM, 군집, ROC
Analyze 메뉴의 Univariate Analysis, K-Means Cluster, ROC Curve에 해당하는 절차입니다.
* 단변량 GLM: 연봉을 부서, 집단, 그리고 두 요인의 상호작용(dept*group)으로 설명합니다.
GLM salary BY dept group
/DESIGN=dept group dept*group.
* K-평균 군집: 만족도 5문항으로 3개 군집을 만들고, 최대 20번까지 중심을 다시 계산합니다.
QUICK CLUSTER q1 q2 q3 q4 q5
/CRITERIA=CLUSTER(3) MXITER(20)
/PRINT=INITIAL.
* ROC 곡선: 향상분(gain)으로 재수강 의향(reenroll=1)을 얼마나 잘 가려내는지 봅니다.
ROC gain BY reenroll (1)
/PLOT=CURVE
/PRINT=SE COORDINATES.
종속변수가 하나인 GLM은 상호작용 항까지 포함해 Type III 제곱합으로 결과를 냅니다. 부서 F=20.71(p<.001), 집단 F=.89(p=.346), 부서×집단 F=2.01(p=.137)입니다.
|부서 | 11111577| 2| 5555789|20.71|.000|
|실험 집단 | 239850.0| 1| 239850.0| .89|.346|
|부서 × 실험 집단| 1077679| 2| 538839.3| 2.01|.137|
각 줄의 열은 왼쪽부터 제곱합, 자유도, 평균제곱, F, 유의확률입니다. 맨 오른쪽 Sig.를 보면 부서만 유의하고, 집단과 상호작용은 유의하지 않습니다. 다시 말해 연봉은 부서에 따라 다르지만, 실험군이냐 대조군이냐에 따라서는 다르지 않고, 부서에 따른 연봉 차이가 집단에 따라 달라지지도 않는다는 뜻입니다. 4편의 일원분산분석(F=22.47)에서 부서에 따라 연봉이 다르다고 나온 결론과도 맞습니다.
K-평균 군집은 만족도 문항으로 세 군집(49, 96, 55명)을 만듭니다. 출력의 최종 군집 중심(Final Cluster Centers) 표를 보면, 1번 군집은 문항 평균이 대략 2점 안팎, 2번은 3점 안팎, 3번은 4점 안팎입니다. 즉 만족도가 낮은 집단, 중간 집단, 높은 집단으로 나뉜 것입니다.
ROC 곡선은 향상분으로 재수강 의향을 예측할 때 AUC=.68로 나오고, 곡선은 png 파일로 그려집니다. AUC는 0.5면 동전 던지기와 같은 수준이고 1에 가까울수록 잘 가려낸다는 뜻이니, 향상분이 재수강 의향을 어느 정도는 구분해 준다고 볼 수 있습니다.

SPSS와 대조
같은 신택스를 SPSS 32에서 돌린 결과입니다.
| 항목 | PSPP 2.1.1 | SPSS 32 | 판정 |
|---|---|---|---|
| SELECT IF 후 N / 평균 | 106 / 8.27 | 106 / 8.266 | 일치 |
| FILTER 후 부서 N | 87 (38/32/17) | 87 (38/32/17) | 일치 |
| WEIGHT 후 남/여 빈도 | 99.00 / 151.50 | 99 / 152 | 표시만 다름 |
| AGGREGATE 부서 평균 연봉 범위 | 3406.63 ~ 3944.36 | 3406.63 ~ 3944.36 | 일치 |
| AGGREGATE 정렬 없이 dept_n | 1~7 (틀림) | 42/75/83 (맞음) | PSPP만 정렬 필요 |
| MATCH FILES 후 부서 평균 향상분 범위 | 4.61 ~ 5.07 | 4.61 ~ 5.07 | 일치 |
| 매크로 4종 | 정상 | 정상 | 일치 |
| GLM 부서 / 집단 / 상호작용 F | 20.71 / .89 / 2.01 | 20.707 / .894 / 2.008 | 일치 |
| K-평균 군집 크기 | 49 / 96 / 55 | 49 / 55 / 96 | 구성 같고 번호만 다름 |
| ROC AUC / 표준오차 | .68 / .04 | .680 / .038 | 일치 |
| ROC 95% 신뢰구간 | .62 ~ .74 | .607 ~ .754 | 차이 |
대부분 일치하고, 눈여겨볼 차이는 세 가지입니다.
첫째, 가중 빈도는 계산값이 같고 보여 주는 방식만 다릅니다. PSPP는 소수를 그대로(151.50) 보여 주고, SPSS는 정수로 반올림해서(152) 보여 줍니다.
둘째, K-평균 군집은 군집 번호를 붙이는 순서만 다릅니다. 크기 49, 96, 55인 세 군집이 양쪽에 똑같이 있고, 번호만 뒤바뀌어 있습니다. 군집 번호 자체에는 의미가 없으니, 비교할 때는 번호가 아니라 군집 중심값을 보고 짝을 맞추시면 됩니다.
셋째, ROC는 AUC와 표준오차는 같은데 95% 신뢰구간이 다릅니다. 신뢰구간을 계산하는 식이 서로 다른 것으로 보입니다. 보고서에 신뢰구간을 적는다면 어느 프로그램의 값인지 밝혀 두시는 것이 좋습니다.
다음 편
8편에서는 PSPP에 없는 절차를 일부러 돌려 봅니다. 어떤 오류가 어떻게 나는지, 그리고 돌아갈 길이 있는지를 살펴보겠습니다.
시리즈 목차: 0편 총론 · 1편 · 2편 · 3편 · 4편 · 5편 · 6편 · 7편 데이터 관리와 매크로 · 8편 · 9편