반응형

[SPSS] 기술 통계 (평균, 표준편차, 표준오차, 최댓값, 최솟값, 중위수, 분위수 등)

 

 1,000명으로 어떤 연구를 했다고 하자. 그들의 키, 몸무게 등 지표들은 서로 다를 것이다. 논문의 저자가 이 모든 것을 독자들에게 보여주고자 한다면 행이 1,000인 표를 제시해야 할 것이다. 그렇게 큰 표를 실어줄 저널이 없기도 하거니와, 독자들이 보기에도 한눈에 들어오지 않는다. 그 대신 키의 '평균', 몸무게의 '평균'을 제시하면 한눈에 들어오니 보기가 좋다. 연속 변수는 평균, 표준편차 등으로 요약을 하여 보여주고, 범주형 자료 (흡연 여부, 음주 여부 등)는 도수분포표 혹은 분할표로 제시하게 된다. 분할표를 작성하는 방법은 다음 링크에서 확인할 수 있다.

2022.09.06 - [기술 통계/SPSS] - [SPSS] 도수분포표 (Frequency table), 분할표 (Contingency table) 만들기

 

어떤 지표로 요약해줄 것인가?

1) 정규성을 따를 때: 평균 및 표준편차

 어떤 변수가 정규 분포를 따른다고 할 수 있다면, 평균과 표준편차만 알면 된다. 단 두 개의 지표만 있으면 전체 분포를 알아낼 수 있기 때문이다. (정규성을 따르는지는 정규성 검정으로 확인할 수 있으며 정규성 검정을 하는 방법은 다음 링크에서 확인할 수 있다.)

2022.08.11 - [기술 통계/SPSS] - [SPSS] 정규성 검정

 

2) 정규성을 따르지 않을 때: 중위수, 최댓값, 최솟값, 분위수, 사분위 범위 등

 정규성을 따르지 않는다면 평균과 표준편차를 안다고 해도 전체 분포를 알아낼 수는 없다. 따라서 분포에 대한 직접적인 정보를 주는데, 예를 들어 '하위 25%에 위치하는 사람의 ALT값은 얼마인가?' 등을 제시하는 것이다. 그런 지표로는 중위수, 최댓값, 최솟값, 분 위수, 사분위 범위 등이 있다.

 

이번 포스팅에서는 이 모든 지표들 (평균, 표준편차, 표준오차, 중위수, 최댓값, 최솟값, 분위수, 사분위 범위 등)을 구하는 법에 대해 소개할 것이다.

 

*실습용 데이터는 아래 링크를 클릭하면 다운로드할 수 있습니다.

2022.08.04 - [공지사항 및 소개] - 분석용 데이터 (update 22.08.29)

 

분석용 데이터 (update 22.08.29)

2022년 08월 29일 버전입니다. 변수는 계속하여 추가될 예정입니다. 다음 카테고리에 있는 글에서 이용된 데이터입니다. - 기술 통계 - 통계 프로그램 사용 방법 1) 엑셀 파일 2) CSV 파일 3) 코드북

medistat.tistory.com

 

먼저 데이터를 불러온다. 데이터를 불러오는 방법은 다음 글을 확인하길 바란다.

2022.08.04 - [통계 프로그램 사용 방법/SPSS] - [SPSS] 데이터 불러오기 및 저장하기

 

SPSS에서는 기술 통계량을 구하는 곳이 세 군데로 나누어져 있다. 일부 기술 통계량은 중복되어 있어서 여러 곳에서 구할 수도 있다. 

 

분석(A)>기술통계량(E)>

 1) 빈도분석(F)

 2) 기술통계(D)

 3) 데이터 탐색(E)

 

각 기술 통계량을 구할 수 있는 곳을 정리해놓은 표는 다음과 같다.

 

  빈도분석 기술통계 데이터 탐색
대상자 수 O O O
결측치 수 O X O
평균 O O O
표준편차 O O O
분산 O O O
표준오차 O O O
최솟값 O O O
최댓값 O O O
중위수 O X O
최빈값 O X X
평균의 신뢰구간 X X O
사분위수 O X O
사분위범위 X X O
백분위수 O X △ (숫자 지정불가)

 

각 방법에 따라 하나씩 살펴보도록 한다.

빈도분석

1) 분석(A)>기술통계량(E)>빈도분석(F)

 

2) 분석하고자 하는 변수 (ALT)를 오른쪽으로 옮기고 "통계량(S)"를 누른다.

 

3) 원하는 통계량 박스를 체크한다. 백분위수를 구하고자 한다면 원하는 백분위 숫자를 입력한 뒤 "추가(A)"를 누른다. 그다음 "계속(C)"를 누른다.

 

4) 연속 변수를 분석하는 경우 "빈도표 표시(D)"박스는 반드시 해제하고, "확인" 버튼을 누른다.

 

결과

 

나와있는 값은 위에서부터 순서대로 다음과 같다.

대상자수

결측치

평균

표준오차

중위수

최빈값

표준편차

분산

최솟값

최댓값

1사분위수

46백분위수

2사분위수(=중위수)

3사분위수

 

하지만 최빈값의 경우 유의해야 한다. 최빈값이 여러 개일 경우 아래 footnote와 같이 "a. 여러 최빈값이 있습니다. 가장 작은 값이 나타납니다."라고 나온다. 즉 지금 표기된 최빈값은 최빈값이 아니므로 신뢰해서는 안 된다는 이야기다.

최빈값이 여러 개라는 것은 다음과 같은 상황을 의미한다.

5개의 숫자 (1, 2, 3, 4, 5)가 있다면 모두 1개씩 있으므로 어떠한 것도 최빈값이라고 할 수 없다.

5개의 숫자 (1, 2, 2, 3, 3)가 있다면 2와 3 둘 다 2개씩 있으므로 2와 3 둘 다 최빈값은 아니다. 즉 최빈값이 없다.

 

사분위수는 SAS, SPSS, R의 결과가 서로 다를 수 있다. 왜냐하면 각 프로그램에서 사분위수를 구하는 방법이 다를 수 있기 때문이다. 각 프로그램에는 사분위수를 구하는 여러가지 방법이 내장되어 있으며, 골라서 사용할 수도 있다.

SAS의 사분위수 확인하기: 2022.09.23 - [기술 통계/SAS] - [SAS] 기술 통계 (평균, 표준편차, 표준오차, 최댓값, 최솟값, 중위수, 분위수 등) - PROC UNIVARIATE, PROC MEANS

R의 사분위수 확인하기: 2022.09.27 - [기술 통계/R] - [R] 기술 통계 (평균, 표준편차, 표준오차, 최댓값, 최솟값, 중위수, 분위수 등)

 

기술통계

1) 분석(A)>기술통계량(E)>기술통계(D)

 

2) 분석하고자 하는 변수 (ALT)를 오른쪽으로 옮기고 "옵션(O)"를 누른다.

 

3) 원하는 통계량 박스를 체크하고 "계속(C)"를 누른다.

4) "확인" 버튼을 누른다.

 

결과

왼쪽에서부터 나오는 통계량을 차례대로 적으면 다음과 같다.

대상자 수

최솟값

최댓값

평균

표준오차

표준편차

분산

 

 

데이터 탐색

1) 분석(A)>기술통계량(E)>데이터 탐색(E)

 

2) 분석하고자 하는 변수 (ALT)를 오른쪽으로 옮기고 "통계량(S)"를 누른다.

 

3) "백분위수(P)" 박스를 체크하고 "계속(C)"을 누른다. 신뢰구간 %를 바꾸고 싶다면 원하는 숫자를 적으면 된다.

 

4) "확인"을 누른다

 

결과

 

조건에 따른 기술 통계량 산출하기

만약 음주 여부에 따른 ALT의 기술 통계량을 산출하고자 한다면 "데이터 탐색"의 "요인"을 사용해야 한다. 요인에 "ALCOHOL"을 넣어주면 된다.

 

결과

결과가 ALCOHOL 값에 따라 따로따로 산출되는 것을 알 수 있다.

 

 

 

만약 데이터 탐색에서 제공하지 않는 "최빈값"이나 "백분위수"를 음주 여부에 따라 구하고자 한다면 어떻게 해야 할까? SPSS의 "케이스 선택" 기능을 사용하여 ALCOHOL=0 혹은 ALCOHOL=1인 사람만 추려내어 빈도 분석을 시행하면 된다.

케이스 선택을 하는 방법은 다음 글에서 확인할 수 있다.

2022.09.29 - [통계 프로그램 사용 방법/SPSS] - [SPSS] 조건에 맞는 데이터만 선택하기

 

SPSS 기술통계 정복 완료!

 

작성일: 2022.09.29.

최종 수정일: 2022.09.29.

이용 프로그램: IBM SPSS v26

운영체제: Windows 10

반응형
반응형

 

[R] 기술 통계 (평균, 표준편차, 표준오차, 최댓값, 최솟값, 중위수, 분위수 등)

 

 1,000명으로 어떤 연구를 했다고 하자. 그들의 키, 몸무게 등 지표들은 서로 다를 것이다. 논문의 저자가 이 모든 것을 독자들에게 보여주고자 한다면 행이 1,000인 표를 제시해야 할 것이다. 그렇게 큰 표를 실어줄 저널이 없기도 하거니와, 독자들이 보기에도 한눈에 들어오지 않는다. 그 대신 키의 '평균', 몸무게의 '평균'을 제시하면 한눈에 들어오니 보기가 좋다. 연속 변수는 평균, 표준편차 등으로 요약을 하여 보여주고, 범주형 자료 (흡연 여부, 음주 여부 등)는 도수분포표 혹은 분할표로 제시하게 된다. 분할표를 작성하는 방법은 다음 링크에서 확인할 수 있다.

2022.08.31 - [기술 통계/R] - [R] 도수분포표 (Frequency table), 분할표 (Contingency table) 만들기 - table(), prop.table(), xtabs(), margin.table()

2022.08.31 - [기술 통계/R] - [R] 도수분포표 (Frequency table), 분할표 (Contingency table) 만들기 - CrossTable()

 

어떤 지표로 요약해줄 것인가?

1) 정규성을 따를 때: 평균 및 표준편차

 어떤 변수가 정규 분포를 따른다고 할 수 있다면, 평균과 표준편차만 알면 된다. 단 두 개의 지표만 있으면 전체 분포를 알아낼 수 있기 때문이다. (정규성을 따르는지는 정규성 검정으로 확인할 수 있으며 정규성 검정을 하는 방법은 다음 링크에서 확인할 수 있다.)

2022.08.11 - [기술 통계/R] - [R] 정규성 검정 (1) : Q-Q plot - qqnorm(), qqline()

2022.08.11 - [기술 통계/R] - [R] 정규성 검정 (2) : 히스토그램 - hist(), dnorm()

2022.08.11 - [기술 통계/R] - [R] 정규성 검정 (3) : 정량적 검정 (Shapiro-Wilk, Kolmogorov-Smirnov) - shapiro.test(), ks.test()

2022.08.12 - [기술 통계/R] - [R] 정규성 검정 (4) : 정량적 검정 (Lilliefors test) - lillie.test()

 

2) 정규성을 따르지 않을 때: 중위수, 최댓값, 최솟값, 분위수, 사분위 범위 등

 정규성을 따르지 않는다면 평균과 표준편차를 안다고 해도 전체 분포를 알아낼 수는 없다. 따라서 분포에 대한 직접적인 정보를 주는데, 예를 들어 '하위 25%에 위치하는 사람의 ALT값은 얼마인가?' 등을 제시하는 것이다. 그런 지표로는 중위수, 최댓값, 최솟값, 분 위수, 사분위 범위 등이 있다.

 

이번 포스팅에서는 이 모든 지표들 (평균, 표준편차, 표준오차, 중위수, 최댓값, 최솟값, 분위수, 사분위 범위 등)을 구하는 법에 대해 소개할 것이다.

 

*실습용 데이터는 아래 링크를 클릭하면 다운로드할 수 있습니다.

2022.08.04 - [공지사항 및 소개] - 분석용 데이터 (update 22.08.29)

 

분석용 데이터 (update 22.08.29)

2022년 08월 29일 버전입니다. 변수는 계속하여 추가될 예정입니다. 다음 카테고리에 있는 글에서 이용된 데이터입니다. - 기술 통계 - 통계 프로그램 사용 방법 1) 엑셀 파일 2) CSV 파일 3) 코드북

medistat.tistory.com

 

 

코드를 보여드리기에 앞서 워킹 디렉토리부터 지정하겠다.

워킹 디렉토리에 관한 설명은 다음 링크된 포스트에서 볼 수 있다.

2022.08.05 - [통계 프로그램 사용 방법/SAS] - [SAS] 라이브러리 만들기 - LIBNAME

setwd("C:/Users/user/Documents/Tistory_blog")

 

데이터를 불러와 df에 객체로 저장하겠다.

데이터 불러오는 방법은 다음 링크에서 볼 수 있다.

2022.08.05 - [통계 프로그램 사용 방법/R] - [R] 데이터 불러오기 : EXCEL - read_excel(), read.xlsx()

2022.08.10 - [통계 프로그램 사용 방법/R] - [R] 데이터 저장하기 : CSV 파일 - write.csv(), write_csv()

2022.08.10 - [통계 프로그램 사용 방법/R] - [R] 데이터 불러오기 : SAS file (.sas7bdat) - read.sas7bdat(), read_sas()

install.packages("readr")
library("readr")
df<-read_csv("Data.csv")

 

코드

이번 포스팅을 일일이 이해하기는 귀찮고 코드만 가져가고 싶은 사람은 다음 코드를 사용하면 된다. :

#기술통계 함수 작성
univariate<-function(x){
  n<-length(x)-sum(is.na(x))
  missing<-sum(is.na(x))
  mean<-mean(x)
  sd<-sd(x)
  var<-var(x)
  se<-sqrt(var/n)
  min<-min(x)
  max<-max(x)
  median<-median(x)
  mode <- function(x) {
    nodup <- unique(x)
    if (length(which(tabulate(match(x, nodup))==max(tabulate(match(x, nodup)))))>=2 )
    {NA}
    else{nodup[which.max(tabulate(match(x, nodup)))]}
  }
  mode<-mode(x)
  lclm<-mean-qt(0.975, n-1)*se
  uclm<-mean+qt(0.975, n-1)*se
  
  P25<-data.frame(quantile(x)[2])[1,1]
  P50<-data.frame(quantile(x)[3])[1,1]
  P75<-data.frame(quantile(x)[4])[1,1]
  qrange<-data.frame(quantile(x)[4])[1,1]-data.frame(quantile(x)[2])[1,1]
  name<-c("N", "N of missing","Mean", "Standard Deviation", "Variation", "Standard Error", "Minimum", 
          "Maximum", "Median", "Mode", "95% Lower limit of mean (two-sided)", "95% Upper limit of mean(two-sided)", "P25", "P50", "P75", "Quantile Range")
  value<-c(n, missing, mean, sd, var, se, min, max, median, mode, lclm, uclm, P25, P50, P75, qrange)
  result<-cbind(name, value)
  print(result)
}

#기술 통계량 계산: "df$ALT"자리에 원하는 변수를 넣으면 된다.
univariate(df$ALT)

 

결과

      name                                  value              
 [1,] "N"                                   "1000"             
 [2,] "N of missing"                        "0"                
 [3,] "Mean"                                "35.11593830339"   
 [4,] "Standard Deviation"                  "5.00643005419849" 
 [5,] "Variation"                           "25.0643418875819" 
 [6,] "Standard Error"                      "0.158317219175875"
 [7,] "Minimum"                             "19.61781834"      
 [8,] "Maximum"                             "49.03881459"      
 [9,] "Median"                              "35.13945912"      
[10,] "Mode"                                NA                 
[11,] "95% Lower limit of mean (two-sided)" "34.8052658601898" 
[12,] "95% Upper limit of mean(two-sided)"  "35.4266107465902" 
[13,] "P25"                                 "31.7559160525"    
[14,] "P50"                                 "35.13945912"      
[15,] "P75"                                 "38.5879822725"    
[16,] "Quantile Range"                      "6.83206622"

"N" : 분석 대상의 수

"N of missing" : 결측치 수

"Mean" : 평균

"Standard Deviation" : 표준 편차

"Variation" : 분산

"Standard Error" : 표준 오차

"Minimum" : 최솟값
"Maximum" : 최댓값

"Median" : 중위수

"Mode" : 최빈값 (최빈값이 여러개인 경우 NA로 표기됨)

"95% Lower limit of mean (two-sided)" : 평균의 95% 신뢰구간의 하한

"95% Upper limit of mean(two-sided)" : 평균의 95% 신뢰구간의 상한

"P25" : 1사분위수

"P50" : 2사분위수 (중위수)

"P75" : 3사분위수

"Quantile Range" : 사분위 범위
 

 

코드 (분석 대상의 수, 결측치 수, 평균, 표준 편차, 분산, 표준 오차)

코드를 하나씩 뜯어 살펴보면 다음과 같다.

univariate<-function(x){
  n<-length(x)-sum(is.na(x))
  missing<-sum(is.na(x))
  mean<-mean(x)
  sd<-sd(x)
  var<-var(x)
  se<-sqrt(var/n)
  }

univariate<-function(x){ :입력되는 값이 x인 함수를 만들건데 함수의 내용은 { }안에 들어있으니 살펴봐라. 그리고 함수의 이름은 univariate이다. 
  n<-length(x)-sum(is.na(x)) : 분석 대상의 수[n]는 전체 개체의 수[length(x)]에서 결측치의 개수 [sum(is.na(x))]를 뺀 값이다.
  missing<-sum(is.na(x)) : 결측된 것을 TRUE로, 결측되지 않은 것을 FALSE로 반환한다 [is.na(x)]. TRUE인 것을 모두 합친다 [sum(is.na(x))]. 그 값이 결측치의 개수이다.
  mean<-mean(x) : 평균은 mean() 함수를 이용한다.
  sd<-sd(x) : 표준편차는 sd() 함수를 이용한다.
  var<-var(x) : 분산은 var() 함수를 이용한다.
  se<-sqrt(var/n) : 표준오차(se)는 분산(var)을 분석 대상의 수(n)로 나눈 뒤 루트를 씌운 값이다.

 

  min<-min(x)
  max<-max(x)
  median<-median(x)
  mode <- function(x) {
    nodup <- unique(x)
    if (length(which(tabulate(match(x, nodup))==max(tabulate(match(x, nodup)))))>=2 )
    {NA}
    else{nodup[which.max(tabulate(match(x, nodup)))]}
  }
  mode<-mode(x)

  min<-min(x) : 최솟값은 min() 함수를 이용한다.
  max<-max(x) : 최댓값은 max() 함수를 이용한다.
  median<-median(x) : 중앙값은 median() 함수를 이용한다.
  mode <- function(x) { : 최빈값은 구하는 함수가 R에 내장되어있지 않으므로 함수를 따로 만들어야 한다. 데이터(x)를 입력받아 최빈값을 구하는 함수를 만들 것이고 그 함수의 이름은 mode이다.
    nodup <- unique(x) : 중복되는 값을 모두 삭제하고 한 개씩만 대표적으로 남긴다. 대표들로 이루어진 벡터를 nodup이라고 하자.
    if (length(which(tabulate(match(x, nodup))==max(tabulate(match(x, nodup)))))>=2 ) 
    {NA}
    else{nodup[which.max(tabulate(match(x, nodup)))]}

여기까지의 내용이 복잡하니 하나씩 코드를 살펴보기로 한다.

(1) 큰 구성은 if (A) {B} else {C} 이다. A라는 조건이 만족하면 B를 반환하고, A를 만족하지 않으면 C를 반환한다는 것이다.

(2) match(x, nodup):  x가 nodup에서 몇 번째 데이터와 일치하는지를 반환하는 함수다.

Example) 예를 들어 x가 (1,5,2,3,3,4,2)라고 하자.

nodup은 중복되는 값을 삭제했을 터이니 (1,5,2,3,4)일 것이다.

그렇다면 match(x,nodup)은 (1,2,3,4,4,5,3)이 된다.

(3) tabulate(match(x,nodup)): tabulate는 각 정수가 나타난 횟수를 세준다. (1,2,3,4,4,5,3)에서 1은 1개, 2는 1개, 3은 2개, 4는 2개, 5는 1개다. 따라서 tabulate(match(x,nodup))은 (1,1,2,2,1)이 된다. 

최빈값은 가장 흔한 단 한 개의 값이어야 하는데, 여기에서 3과 4는 2개, 나머지는 1개이므로 이 데이터의 최빈값은 없다. 즉, tabulate(match(x,nodup))인 (1,1,2,2,1)의 최댓값(2)이 tabulate(match(x,nodup))인 (1,1,2,2,1)에 2개 이상 존재한다면 최빈값이 없다고 반환해야 한다. 

(4) tabulate(match(x, nodup))==max(tabulate(match(x, nodup))): tabulate(match(x,nodup))인 (1,1,2,2,1)이 tabulate(match(x,nodup))인 (1,1,2,2,1)의 최댓값(2)과 같은지를 확인해주는 코드다 결과는 (FALSE, FALSE, TRUE, TRUE, FALSE)이다. 

(5) which(tabulate(match(x, nodup))==max(tabulate(match(x, nodup))))는 TRUE인 위치를 반환하므로 (3,4)를 보여준다. 

(6) length(which(tabulate(match(x, nodup))==max(tabulate(match(x, nodup)))))는 (3,4)에 있는 숫자의 개수, 즉 2를 반환한다. 

이렇게 함으로써 최빈값'같은' 값이 2개 이상 존재할 때 NA를 반환하도록 하였다.

 

그렇지 않을 때 (즉, 단 한 개의 최빈값이 존재할 때)는 다음과 같은 로직에 의해 구해진다고 생각하면 된다.

Example) x가 (1,5,2,2,3)이라고 하자.

nodup은 (1,5,2,3)이 된다.

match(x,nodup)은 (1,2,3,3,4)이 된다.

tabulate(match(x,nodup))는 (1,1,2,1)이 된다. 여기에서 횟수가 가장 많아 '2'라고 표현된 값의 근원을 찾아가야 한다.

which.max(tabulate(match(x, nodup)))는 (1,1,2,1)에서 최댓값이 존재하는 위치를 반환하므로 3이 된다.

(1,1,2,1)의 2는 match(x,nodup)인 (1,2,3,3,4)에서 온 것이다. 1이 1개, 2가 1개, 32개, 4가 1개. 즉, tabulate는 개수를 세어주므로 중복된 값을 빼는 효과가 있다. 즉 23번째에 위치한 이유는 nodup (1,5,2,3)의 2가 nodup에서 3번째에 위치해있기 때문이다. 따라서 nodup의 3번째 값을 반환해야 최빈값을 구할 수 있다. 그러므로 nodup[which.max(tabulate(match(x, nodup)))]이라는 코드를 쓰게 된다.

  }
  mode<-mode(x)

 

  lclm<-mean-qt(0.975, n-1)*se
  uclm<-mean+qt(0.975, n-1)*se
  
  P25<-data.frame(quantile(x)[2])[1,1]
  P50<-data.frame(quantile(x)[3])[1,1]
  P75<-data.frame(quantile(x)[4])[1,1]
  qrange<-data.frame(quantile(x)[4])[1,1]-data.frame(quantile(x)[2])[1,1]
  name<-c("N", "N of missing","Mean", "Standard Deviation", "Variation", "Standard Error", "Minimum", 
          "Maximum", "Median", "Mode", "95% Lower limit of mean (two-sided)", "95% Upper limit of mean(two-sided)", "P25", "P50", "P75", "Quantile Range")
  value<-c(n, missing, mean, sd, var, se, min, max, median, mode, lclm, uclm, P25, P50, P75, qrange)
  result<-cbind(name, value)
  print(result)
}

 

  lclm<-mean-qt(0.975, n-1)*se : t 분포에서 자유도(n-1)에 걸맞게 2.5%에 해당하는 값을 찾고, 표준오차를 곱하여 평균에서 빼면 95% 신뢰구간의 하한이 구해진다. 
  uclm<-mean+qt(0.975, n-1)*se : t 분포에서 자유도(n-1)에 걸맞게 2.5%에 해당하는 값을 찾고, 표준오차를 곱하여 평균에서 더하면 95% 신뢰구간의 상한이 구해진다.
  
  P25<-data.frame(quantile(x)[2])[1,1] : quantile() 함수의 2번째 값은 1사분위수를 의미한다. 데이터프레임으로 바꾸고 값만을 취한다.
  P50<-data.frame(quantile(x)[3])[1,1] : quantile() 함수의 2번째 값은 2사분위수를 의미한다. 데이터프레임으로 바꾸고 값만을 취한다.
  P75<-data.frame(quantile(x)[4])[1,1] : quantile() 함수의 2번째 값은 3사분위수를 의미한다. 데이터프레임으로 바꾸고 값만을 취한다.
  qrange<-data.frame(quantile(x)[4])[1,1]-data.frame(quantile(x)[2])[1,1] : 3사분위수에서 1사분위수를 빼어 값을 구한다.
  name<-c("N", "N of missing","Mean", "Standard Deviation", "Variation", "Standard Error", "Minimum", 
          "Maximum", "Median", "Mode", "95% Lower limit of mean (two-sided)", "95% Upper limit of mean(two-sided)", "P25", "P50", "P75", "Quantile Range") : 각 값의 이름을 지정하여 name이라는 벡터에 저장한다.
  value<-c(n, missing, mean, sd, var, se, min, max, median, mode, lclm, uclm, P25, P50, P75, qrange) : 위에서 구한 값들로 벡터를 만들고 value라는 이름을 붙인다.
  result<-cbind(name, value) : name과 value를 열 별로 합치고 result에 저장한다.
  print(result) : result를 출력한다.
}

 

 

만약 25%, 50%, 75%가 아닌 임의의 n% 백분위수를 구하고 싶다면 Pn을 사용하면 된다.

64%백분위수를 보고싶다면 P64를 사용하면 된다.

 

사분위수는 SAS, SPSS, R의 결과가 서로 다를 수 있다. 왜냐하면 각 프로그램에서 사분위수를 구하는 방법이 다를 수 있기 때문이다. 각 프로그램에는 사분위수를 구하는 여러가지 방법이 내장되어 있으며, 골라서 사용할 수도 있다.

SAS의 사분위수 확인하기:2022.09.23 - [기술 통계/SAS] - [SAS] 기술 통계 (평균, 표준편차, 표준오차, 최댓값, 최솟값, 중위수, 분위수 등) - PROC UNIVARIATE, PROC MEANS

SPSS의 사분위수 확인하기: 2022.09.29 - [기술 통계/SPSS] - [SPSS] 기술 통계 (평균, 표준편차, 표준오차, 최댓값, 최솟값, 중위수, 분위수 등)

 

 

R 기술 통계량 정복 완료!

 

작성일: 2022.09.27.

최종 수정일: 2022.09.29.

이용 프로그램: R 4.1.3

RStudio v1.4.1717

RStudio 2021.09.1+372 "Ghost Orchid" Release 

운영체제: Windows 10, Mac OS 10.15.7

반응형
반응형

[SAS] 기술 통계 (평균, 표준편차, 표준오차, 최댓값, 최솟값, 중위수, 분위수 등) - PROC UNIVARIATE, PROC MEANS

 

 1,000명으로 어떤 연구를 했다고 하자. 그들의 키, 몸무게 등 지표들은 서로 다를 것이다. 논문의 저자가 이 모든 것을 독자들에게 보여주고자 한다면 행이 1,000인 표를 제시해야 할 것이다. 그렇게 큰 표를 실어줄 저널이 없기도 하거니와, 독자들이 보기에도 한눈에 들어오지 않는다. 그 대신 키의 '평균', 몸무게의 '평균'을 제시하면 한눈에 들어오니 보기가 좋다. 연속 변수는 평균, 표준편차 등으로 요약을 하여 보여주고, 범주형 자료 (흡연 여부, 음주 여부 등)는 도수분포표 혹은 분할표로 제시하게 된다. 분할표를 작성하는 방법은 다음 링크에서 확인할 수 있다. 2022.08.18 - [기술 통계/SAS] - [SAS] 도수분포표 (Frequency table), 분할표 (Contingency table) 만들기 - PROC FREQ

 

 

어떤 지표로 요약해줄 것인가?

1) 정규성을 따를 때: 평균 및 표준편차

 어떤 변수가 정규 분포를 따른다고 할 수 있다면, 평균과 표준편차만 알면 된다. 단 두 개의 지표만 있으면 전체 분포를 알아낼 수 있기 때문이다. (정규성을 따르는지는 정규성 검정으로 확인할 수 있으며 정규성 검정을 하는 방법은 다음 링크에서 확인할 수 있다.) 2022.08.12 - [기술 통계/SAS] - [SAS] 정규성 검정 - PROC UNIVARIATE

 

2) 정규성을 따르지 않을 때: 중위수, 최댓값, 최솟값, 분위수, 사분위 범위 등

 정규성을 따르지 않는다면 평균과 표준편차를 안다고 해도 전체 분포를 알아낼 수는 없다. 따라서 분포에 대한 직접적인 정보를 주는데, 예를 들어 '하위 25%에 위치하는 사람의 ALT값은 얼마인가?' 등을 제시하는 것이다. 그런 지표로는 중위수, 최댓값, 최솟값, 분 위수, 사분위 범위 등이 있다.

 

이번 포스팅에서는 이 모든 지표들 (평균, 표준편차, 표준오차, 중위수, 최댓값, 최솟값, 분위수, 사분위 범위 등)을 구하는 법에 대해 소개할 것이다.

 

*실습용 데이터는 아래 링크를 클릭하면 다운로드할 수 있습니다.

2022.08.04 - [공지사항 및 소개] - 분석용 데이터 (update 22.08.29)

 

분석용 데이터 (update 22.08.29)

2022년 08월 29일 버전입니다. 변수는 계속하여 추가될 예정입니다. 다음 카테고리에 있는 글에서 이용된 데이터입니다. - 기술 통계 - 통계 프로그램 사용 방법 1) 엑셀 파일 2) CSV 파일 3) 코드북

medistat.tistory.com

 

시작하기 위해 라이브러리를 만들고, 파일을 불러온다.

라이브러리 만드는 방법: 2022.08.05 - [통계 프로그램 사용 방법/SAS] - [SAS] 라이브러리 만들기 - LIBNAME

파일 불러오는 방법: 2022.08.05 - [통계 프로그램 사용 방법/SAS] - [SAS] 데이터 불러오기 및 저장하기 - PROC IMPORT, PROC EXPORT

 

*라이브러리 지정하기;
LIBNAME hong "C:/Users/User/Documents/Tistory_blog";

*파일 불러오기;
PROC IMPORT
DATAFILE="C:\Users\user\Documents\Tistory_blog\Data.xlsx"
DBMS=EXCEL
OUT=hong.df
REPLACE;
RUN;


초보자용 (PROC UNIVARIATE)

제목에서도 알 수 있듯이 SAS에서 기술 통계량을 확인하는 방법은 대표적으로 PROC UNIVARIATE와 PROC MEANS가 있다. 둘 다 유용하지만 별다른 설정이 필요 없는 PROC UNIVARIATE가 초보자에게는 권장된다. 

 

 

코드

PROC UNIVARIATE DATA=hong.df ;
VAR ALT ;
RUN;

PROC UNIVARIATE DATA=hong.df : 기술 통계량을 산출하는 코드를 시작할 것이고, 데이터는 hong 라이브러리에 있는 df를 쓰겠다.
VAR ALT : 변수 "ALT"에 대한 기술 통계량을 보여달라.

결과

 

일반적으로 원하는 대부분의 통계량을 확인할 수 있다.

N(대상자수) 1000명

평균: 35.1159383

표준 편차: 5.00643005

분산: 25.0643419

표준 오차: 0.15831722

사분위수 범위(IQR, InterQuartile Range): 6.83472

 - 이 값은 Q3 (75 백분위수)에서 Q1 (25 백분위수)를 뺀 값과 같다.

최댓값: 49.0388

Q3 (75 백분위수): 38.5897

중위수 (50 백분위수): 35.1395

Q1 (25 백분위수): 31.7550

최솟값: 19.6178

 

사분위수는 SAS, SPSS, R의 결과가 서로 다를 수 있다. 왜냐하면 각 프로그램에서 사분위수를 구하는 방법이 다를 수 있기 때문이다. 각 프로그램에는 사분위수를 구하는 여러가지 방법이 내장되어 있으며, 골라서 사용할 수도 있다.

R의 사분위수 확인하기: 2022.09.27 - [기술 통계/R] - [R] 기술 통계 (평균, 표준편차, 표준오차, 최댓값, 최솟값, 중위수, 분위수 등)

SPSS의 사분위수 확인하기: 2022.09.29 - [기술 통계/SPSS] - [SPSS] 기술 통계 (평균, 표준편차, 표준오차, 최댓값, 최솟값, 중위수, 분위수 등)

 

코드

만약, 음주 여부에 따라 기술 통계량을 보고 싶다면 다음과 같이 "CLASS"구문을 추가하면 된다.

PROC UNIVARIATE DATA=hong.df ;
CLASS ALCOHOL;
VAR ALT ;

PROC UNIVARIATE DATA=hong.df : 기술 통계량을 산출하는 코드를 시작할 것이고, 데이터는 hong 라이브러리에 있는 df를 쓰겠다.

CLASS ALCOHOL : 음주 여부에 따라서 각각 결과를 산출하라
VAR ALT : 변수 "ALT"에 대한 기술 통계량을 보여달라.

 

결과

 

경력자용 (PROC MEANS)

 PROC UNIVARIATE은 정말 훌륭한 코드이지만 단점은 출력되는 결괏값이 너무 많다는 것이다. 그중에 필요한 것만 골라서 보고 싶다면 PROC MEANS가 더욱 적절하다. 물론 SAS에 익숙하지 않다면 코드가 복잡하게 느껴질 수도 있다.

 

기본 코드

PROC MEANS DATA=hong.df ;
VAR ALT ;
RUN;

PROC MEANS DATA=hong.df : 기술 통계량을 산출하는 코드를 시작할 것이고, 데이터는 hong 라이브러리에 있는 df를 쓰겠다.
VAR ALT : 변수 "ALT"에 대한 기술 통계량을 보여달라.

 

결과

보고 싶은 통계량을 지정해놓지 않으면 표본의 수, 평균, 표준편차, 최솟값, 최댓값을 보여준다.

 

코드

보고 싶은 통계량이 있다면 데이터 지정 후 모두 다 적어주면 된다.

예를 들어 표본의 수는 N, 평균은 MEAN, 표준편차는 STD인데 이 세 가지를 넣은 코드는 다음과 같다.

PROC MEANS DATA=hong.df N MEAN STD;
VAR ALT ;
RUN;

PROC MEANS DATA=hong.df N MEAN STD : 기술 통계량을 산출하는 코드를 시작할 것이고, 데이터는 hong 라이브러리에 있는 df를 쓰겠다. 통계량은 표본의 수, 평균, 표준편차만 보여달라.
VAR ALT : 변수 "ALT"에 대한 기술 통계량을 보여달라.

결과

 

비교적 자주 쓰는 통계량의 코드는 다음과 같다.

통계량 코드 통계량 코드
표본 수 N 평균의 신뢰구간 CLM
결측 수 NMISS 25백분위수 (1사분위수) P25 (Q1)
평균 MEAN 75백분위수 (3사분위수) P75 (Q3)
표준편차 STD 사분위 범위  QRANGE
표준오차 STDERR 1백분위수 P1
최솟값 MIN 5백분위수 P5
최댓값 MAX n0백분위수 Pn0 (i.e. P10, P20, P30, ...)
중위수 MEDIAN 95백분위수 P95
최빈값 MODE 99백분위수 P99

*CLM은 양측(two-sided) 신뢰구간을 구해준다. 만약 단측 (one-sided)신뢰구간을 구하고자 한다면 신뢰구간의 상한은 UCLM을, 하한은 LCLM을 사용하면 된다.

코드

만약, 음주 여부에 따라 기술 통계량을 보고 싶다면 다음과 같이 "CLASS"구문을 추가하면 된다.

PROC MEANS DATA=hong.df N MEAN STD;
CLASS ALCOHOL;
VAR ALT ;
RUN;

PROC MEANS DATA=hong.df N MEAN STD : 기술 통계량을 산출하는 코드를 시작할 것이고, 데이터는 hong 라이브러리에 있는 df를 쓰겠다. 통계량은 표본의 수, 평균, 표준편차만 보여달라.

CLASS ALCOHOL : 음주 여부에 따라서 각각 결과를 산출하라
VAR ALT : 변수 "ALT"에 대한 기술 통계량을 보여달라.

 

결과

 

코드

만약, 음주 여부에 따라 ALT와 수축기 혈압을 동시에 보고 싶다면 변수 자리에 수축기 혈압 변수를 같이 쓰면 된다.

PROC MEANS DATA=hong.df N MEAN STD;
CLASS ALCOHOL;
VAR ALT SBP;
RUN;

PROC MEANS DATA=hong.df N MEAN STD : 기술 통계량을 산출하는 코드를 시작할 것이고, 데이터는 hong 라이브러리에 있는 df를 쓰겠다. 통계량은 표본의 수, 평균, 표준편차만 보여달라.

CLASS ALCOHOL : 음주 여부에 따라서 각각 결과를 산출하라
VAR ALT SBP : 변수 "ALT"와 "SBP"에 대한 기술 통계량을 보여달라.

 

결과

코드 정리

*라이브러리 지정하기;
LIBNAME hong "C:/Users/User/Documents/Tistory_blog";

*파일 불러오기;
PROC IMPORT
DATAFILE="C:\Users\user\Documents\Tistory_blog\Data.xlsx"
DBMS=EXCEL
OUT=hong.df
REPLACE;
RUN;

*초보자용;
PROC UNIVARIATE DATA=hong.df ;
VAR ALT ;
RUN;

*(초보자용) 음주 여부에 따른 기술 통계량;
PROC UNIVARIATE DATA=hong.df ;
CLASS ALCOHOL;
VAR ALT ;

*경력자용;
PROC MEANS DATA=hong.df ;
VAR ALT ;
RUN;

*(경력자용) 음주 여부에 따른 기술 통계량;
PROC MEANS DATA=hong.df N MEAN STD;
CLASS ALCOHOL;
VAR ALT ;
RUN;

 

SAS 기술 통계량 정복 완료!

 

작성일: 2022.09.23.

최종 수정일: 2022.09.29.

이용 프로그램: SAS v9.4

운영체제: Windows 10

반응형
반응형

[SPSS] 도수분포표 (Frequency table), 분할표 (Contingency table) 만들기

 

 수천 명의 정보를 포함한 데이터를 한눈에 요약하고 싶을 때가 많다. 나이, 혈압과 같은 연속형 변수는 평균으로 요약하곤 하는데, 성별이나 음주 여부는 평균을 구할 수 없으니 빈도를 제시하곤 한다. 이를 표로 제시하면 도수분포표 (Frequency table)가 된다. 이를 넘어서 남성 중 음주자가 몇 명인지, 여성중 비음주자가 몇 명인지 알고 싶을 때가 있는데, 이때 사용하는 것이 분할표 (Contingency table)이다. 즉 본 글의 목적은 다음 두 개의 표 내용을 채우는 것이다.

 

<도수분포표>

  빈도 백분율 누적백분율
여성      
남성      

 

<분할표>

  비음주자 음주자 합계
여성      
남성      
합계      

 

 

*실습용 데이터는 아래 링크를 클릭하면 다운로드할 수 있습니다.

2022.08.04 - [공지사항 및 소개] - 분석용 데이터 (update 22.08.29)

 

분석용 데이터 (update 22.08.29)

2022년 08월 29일 버전입니다. 변수는 계속하여 추가될 예정입니다. 다음 카테고리에 있는 글에서 이용된 데이터입니다. - 기술 통계 - 통계 프로그램 사용 방법 1) 엑셀 파일 2) CSV 파일 3) 코드북

medistat.tistory.com

 

먼저 데이터를 불러온다. 데이터를 불러오는 방법은 다음 글을 확인하길 바란다.

2022.08.04 - [통계 프로그램 사용 방법/SPSS] - [SPSS] 데이터 불러오기 및 저장하기

 

도수분포표 작성하기

1) 분석(A) > 기술통계량(E) > 빈도분석(F) 

 

2) 분석하고자 하는 변수(SEX)를 오른쪽으로 옮기고 "확인" 누르기

 

결과

빈도: 각 카테고리에 속하는 사람의 수

퍼센트: 전체 인구 (결측값 포함)에서 각 카테고리에 속하는 사람이 차지하는 분율

 - 따라서 결측값이 있는 경우 퍼센트의 총합은 100이 안 될 수 있다.

유효 퍼센트: 결측치를 제외한 인구에서 각 카테고리에 속하는 사람이 차지하는 분율 

 - 따라서 결측치 유무에 관계없이 유효 퍼센트의 총합은 100이 된다.

누적 퍼센트: 유효 퍼센트를 누적으로 더한 것

 

본 데이터에는 결측치가 없으므로 퍼센트와 유효 퍼센트는 같은 값으로 나온다. 보통의 경우 결측치를 제외했을 때의 퍼센트를 구하니 "유효 퍼센트"를 사용하면 된다. 도수분포표를 채우면 다음과 같다.

 

  빈도 백분율 누적백분율
여성 482 48.2 48.2
남성 518 51.8 100.0

 

분할표 작성하기

1) 분석(A) > 기술통계량(E) > 교차분석(C) 

 

2) 행과 열에 원하는 변수를 넣어주기. 여기에서는 행에 SEX를, 열에 ALCOHOL을 넣었다. 그리고 셀(E)을 클릭한다.

 

3) 퍼센트 박스의 세 개의 체크 박스를 모두 선택한다. 계속 (C)를 누른다.

4) "확인"버튼을 누른다.

결과

 

각 내용은 다음과 같다. 

 

각 셀 안의 내용물은 다음과 같다

(1) 빈도 - 각 셀에 해당하는 인구의 수

  비음주자 음주자 합계
여성 236
49.0%
57.6%
23.6%
246
51.0%
41.7%
24.6%
482
100.0%
48.2%
48.2%
남성 174
33.6%
42.4%
17.4%
344
66.4%
58.3%
34.4%
518
100.0%
51.8%
51.8%
합계 410
41.0%
100.0%
41.0%
590
59.0%
100.0%
59.0%
1000
100.0%
100.0%
100.0%

 

 

(2) 행 백분율 - 각 행에서 빈도가 차지하는 분율.

 - 여성에서 비음주자가 차지하는 분율은 49.0%, 음주자가 차지하는 분율은 51.0%다.

 - 남성에서 비음주자가 차지하는 분율은 33.6%, 음주자가 차지하는 분율은 66.4%다.

따라서 행별로 더하면 (=같은 색깔끼리 더하면) 100%가 나오게 된다.

  비음주자 음주자 합계
여성 236
49.0%
57.6%
23.6%
246
51.0%
41.7%
24.6%
482
100.0%
48.2%
48.2%
남성 174
33.6%
42.4%
17.4%
344
66.4%
58.3%
34.4%
518
100.0%
51.8%
51.8%
합계 410
41.0%
100.0%
41.0%
590
59.0%
100.0%
59.0%
1000
100.0%
100.0%
100.0%

(3) 열 백분율 - 각 열(칼럼)에서 빈도가 차지하는 분율.

 - 비음주자에서 여성이 차지하는 분율은 57.6%, 남성이 차지하는 분율은 42.4%다.

 - 음주자에서 여성이 차지하는 분율은 41.7%, 남성이 차지하는 분율은 58.3%다.

따라서 열(칼럼) 별로 더하면 (=같은 색깔끼리 더하면) 100%가 나오게 된다.

  비음주자 음주자 합계
여성 236
49.0%
57.6%
23.6%
246
51.0%
41.7%
24.6%
482
100.0%
48.2%
48.2%
남성 174
33.6%
42.4%
17.4%
344
66.4%
58.3%
34.4%
518
100.0%
51.8%
51.8%
합계 410
41.0%
100.0%
41.0%
590
59.0%
100.0%
59.0%
1000
100.0%
100.0%
100.0%

 

(4) 백분율 - 빈도를 전체 인구 (1,000)으로 나눠 %로 나타낸 값

세로 혹은 가로로 더하면 합계의 백분율과 일치하며 백분율의 총합은 100과 같다.

  비음주자 음주자 합계
여성 236
49.0%
57.6%
23.6%
246
51.0%
41.7%
24.6%
482
100.0%
48.2%
48.2%
남성 174
33.6%
42.4%
17.4%
344
66.4%
58.3%
34.4%
518
100.0%
51.8%
51.8%
합계 410
41.0%
100.0%
41.0%
590
59.0%
100.0%
59.0%
1000
100.0%
100.0%
100.0%

 

 

세 개 이상의 변수를 사용하는 분할표

세 개 이상의 변수를 사용하여 분할표를 작성하고 싶을 때가 있다. 조건에 따라 분할표를 작성하는 경우가 해당하는데 예를 들어 고혈압 여부에 따른 성별-음주의 분할표를 그려보도록 하겠다.

 

1) 분석(A) > 기술통계량(E) > 교차분석(C) 

 

2) 행과 열에 원하는 변수를 넣어주기. 여기에서는 행에 SEX를, 열에 ALCOHOL을 넣었다. 조건 (고혈압 여부)에 해당하는 변수인 HTN을 레이어에 넣는다. 그리고 셀(E)을 클릭한다.

 

3) 퍼센트 박스의 세 개의 체크 박스를 모두 선택한다. 계속 (C)를 누른다.

4) "확인"버튼을 누른다.

결과

고혈압이 없는 (HTN=0) 사람의 성별-음주 분할표가 위에 나오고, 고혈압이 있는 (HTN=1) 사람의 성별-음주 분할표가 따라 나오게 된다. 

 

SPSS 도수분포표, 분할표 정복 완료!

 

작성일: 2022.09.06.

최종 수정일: 2022.09.06.

이용 프로그램: IBM SPSS v26

운영체제: Windows 10

반응형
반응형

 

[R] 도수분포표 (Frequency table), 분할표 (Contingency table) 만들기 - CrossTable()

 

 이전 글에서 R로 도수분포표 및 분할표를 만드는 것이 얼마나 귀찮은 일인지 설명하였다. 이 글은 아래 글의 후속 글이므로 미리 읽고 오길 권한다.

2022.08.31 - [기술 통계/R] - [R] 도수분포표 (Frequency table), 분할표 (Contingency table) 만들기 - table(), prop.table(), xtabs(), margin.table()

 

[R] 도수분포표 (Frequency table), 분할표 (Contingency table) 만들기 - table(), prop.table(), xtabs(), margin.table()

[R] 도수분포표 (Frequency table), 분할표 (Contingency table) 만들기 - table(), prop.table(), xtabs(), margin.table()  수천 명의 정보를 포함한 데이터를 한눈에 요약하고 싶을 때가 많다...

medistat.tistory.com

 

이 귀찮은 일을 한꺼번에 해주는 함수로 CrossTable()이 있다. 이를 소개하고 한계점 및 일부 해결 방안을 소개한다.

 

 

*실습용 데이터는 아래 링크를 클릭하면 다운로드할 수 있습니다.

2022.08.04 - [공지사항 및 소개] - 분석용 데이터 (update 22.08.29)

 

분석용 데이터 (update 22.08.29)

2022년 08월 29일 버전입니다. 변수는 계속하여 추가될 예정입니다. 다음 카테고리에 있는 글에서 이용된 데이터입니다. - 기술 통계 - 통계 프로그램 사용 방법 1) 엑셀 파일 2) CSV 파일 3) 코드북

medistat.tistory.com

 

코드를 보여드리기에 앞서 워킹 디렉토리부터 지정하겠다.

워킹 디렉토리에 관한 설명은 다음 링크된 포스트에서 볼 수 있다.

2022.08.05 - [통계 프로그램 사용 방법/SAS] - [SAS] 라이브러리 만들기 - LIBNAME

setwd("C:/Users/user/Documents/Tistory_blog")

 

데이터를 불러와 df에 객체로 저장하겠다.

데이터 불러오는 방법은 다음 링크에서 볼 수 있다.

2022.08.05 - [통계 프로그램 사용 방법/R] - [R] 데이터 불러오기 : EXCEL - read_excel(), read.xlsx()

2022.08.10 - [통계 프로그램 사용 방법/R] - [R] 데이터 저장하기 : CSV 파일 - write.csv(), write_csv()

2022.08.10 - [통계 프로그램 사용 방법/R] - [R] 데이터 불러오기 : SAS file (.sas7bdat) - read.sas7bdat(), read_sas()

 

install.packages("readr")
library("readr")
df<-read_csv("Data.csv")

 

CrossTable() 함수는 gmodels라는 패키지에 있으므로 패키지를 설치한다.

패키지 설치 방법은 다음 글에서 볼 수 있다.

2022.08.05 - [통계 프로그램 사용 방법/R] - [R] 패키지 설치하기 - install.packages(), library()

install.packages("gmodels")
library("gmodels")

 

코드

성별과 음주 여부에 대해 분할표를 작성하도록 하겠다.

CrossTable(df$SEX, df$ALCOHOL, prop.chisq=FALSE)

CrossTable(df$SEX, df$ALCOHOL, prop.chisq=FALSE) : 데이터 df에 있는 SEX와 ALCOHOL로 교차 표를 출력한다. 카이 제곱 검정 기여량은 출력하지 않는다. (백분율, 행백분율, 열백분율은 출력하는 것이 기본 설정이다.)

 

결과

   Cell Contents
|-------------------------|
|                       N |
|           N / Row Total |
|           N / Col Total |
|         N / Table Total |
|-------------------------|

 
Total Observations in Table:  1000 

 
             | df$ALCOHOL 
      df$SEX |         0 |         1 | Row Total | 
-------------|-----------|-----------|-----------|
           0 |       236 |       246 |       482 | 
             |     0.490 |     0.510 |     0.482 | 
             |     0.576 |     0.417 |           | 
             |     0.236 |     0.246 |           | 
-------------|-----------|-----------|-----------|
           1 |       174 |       344 |       518 | 
             |     0.336 |     0.664 |     0.518 | 
             |     0.424 |     0.583 |           | 
             |     0.174 |     0.344 |           | 
-------------|-----------|-----------|-----------|
Column Total |       410 |       590 |      1000 | 
             |     0.410 |     0.590 |           | 
-------------|-----------|-----------|-----------|

이전 글 (2022.08.31 - [기술 통계/R] - [R] 도수분포표 (Frequency table), 분할표 (Contingency table) 만들기 - table(), prop.table(), xtabs(), margin.table())과 거의 같은 결과가 도출된다.

 

코드-퍼센트를 산출 및 소수점 이하 숫자 제한하고 싶을 때

CrossTable(df$SEX, df$ALCOHOL, prop.chisq=FALSE, format=c("SPSS"), digits=2)

결과

  Cell Contents
|-------------------------|
|                   Count |
|             Row Percent |
|          Column Percent |
|           Total Percent |
|-------------------------|

Total Observations in Table:  1000 

             | df$ALCOHOL 
      df$SEX |        0  |        1  | Row Total | 
-------------|-----------|-----------|-----------|
           0 |      236  |      246  |      482  | 
             |    48.96% |    51.04% |    48.20% | 
             |    57.56% |    41.69% |           | 
             |    23.60% |    24.60% |           | 
-------------|-----------|-----------|-----------|
           1 |      174  |      344  |      518  | 
             |    33.59% |    66.41% |    51.80% | 
             |    42.44% |    58.31% |           | 
             |    17.40% |    34.40% |           | 
-------------|-----------|-----------|-----------|
Column Total |      410  |      590  |     1000  | 
             |    41.00% |    59.00% |           | 
-------------|-----------|-----------|-----------|

 

참 강력한 툴이지만 단점이 존재한다.

 

1) 도수분포표의 경우 누적 도수를 산출해주지 않는다.

2) 세 개 이상의 변수를 사용한 분할표를 작성해주지 않는다.

 

첫 번째 단점은 해결할 수 없다.

두 번째 단점인 "세 개 이상의 변수를 사용한 분할표"는 억지로 작성할 수는 있다. 

성별과 음주 여부에 관한 분할표를 고혈압 여부에 따라 작성하고자 한다고 하자. 그렇다면 고혈압이 있는 집단과 없는 집단을 미리 나눠놔야 한다.

 

코드

subsample_wohtn<-df[df$HTN==0,]
subsample_whtn<-df[df$HTN==1,]

CrossTable(subsample_wohtn$SEX, subsample_wohtn$ALCOHOL, prop.chisq=FALSE)
CrossTable(subsample_whtn$SEX, subsample_whtn$ALCOHOL, prop.chisq=FALSE)

subsample_wohtn<-df[df$HTN==0,] : 데이터 df의 HTN변수가 0인 사람만 뽑아 "subsample_wohtn"에 저장한다.
subsample_whtn<-df[df$HTN==1,] : 데이터 df의 HTN변수가 1인 사람만 뽑아 "subsample_whtn"에 저장한다.

CrossTable(subsample_wohtn$SEX, subsample_wohtn$ALCOHOL, prop.chisq=FALSE) : HTN변수가 0인 사람들로만 성별과 음주 여부의 분할표를 작성한다.
CrossTable(subsample_whtn$SEX, subsample_whtn$ALCOHOL, prop.chisq=FALSE) : HTN변수가 1인 사람들로만 성별과 음주 여부의 분할표를 작성한다.

 

결과

   Cell Contents
|-------------------------|
|                       N |
|           N / Row Total |
|           N / Col Total |
|         N / Table Total |
|-------------------------|

 
Total Observations in Table:  503 

 
                    | subsample_wohtn$ALCOHOL 
subsample_wohtn$SEX |         0 |         1 | Row Total | 
--------------------|-----------|-----------|-----------|
                  0 |       114 |       122 |       236 | 
                    |     0.483 |     0.517 |     0.469 | 
                    |     0.562 |     0.407 |           | 
                    |     0.227 |     0.243 |           | 
--------------------|-----------|-----------|-----------|
                  1 |        89 |       178 |       267 | 
                    |     0.333 |     0.667 |     0.531 | 
                    |     0.438 |     0.593 |           | 
                    |     0.177 |     0.354 |           | 
--------------------|-----------|-----------|-----------|
       Column Total |       203 |       300 |       503 | 
                    |     0.404 |     0.596 |           | 
--------------------|-----------|-----------|-----------|





   Cell Contents
|-------------------------|
|                       N |
|           N / Row Total |
|           N / Col Total |
|         N / Table Total |
|-------------------------|

 
Total Observations in Table:  497 

 
                   | subsample_whtn$ALCOHOL 
subsample_whtn$SEX |         0 |         1 | Row Total | 
-------------------|-----------|-----------|-----------|
                 0 |       122 |       124 |       246 | 
                   |     0.496 |     0.504 |     0.495 | 
                   |     0.589 |     0.428 |           | 
                   |     0.245 |     0.249 |           | 
-------------------|-----------|-----------|-----------|
                 1 |        85 |       166 |       251 | 
                   |     0.339 |     0.661 |     0.505 | 
                   |     0.411 |     0.572 |           | 
                   |     0.171 |     0.334 |           | 
-------------------|-----------|-----------|-----------|
      Column Total |       207 |       290 |       497 | 
                   |     0.416 |     0.584 |           | 
-------------------|-----------|-----------|-----------|

 

 

 

 

[R] 도수분포표 (Frequency table), 분할표 (Contingency table) 만들기 정복 완료!

 

작성일: 2022.08.31.

최종 수정일: 2022.08.31.

이용 프로그램: R 4.1.3

RStudio v1.4.1717

RStudio 2021.09.1+372 "Ghost Orchid" Release 

운영체제: Windows 10, Mac OS 10.15.7

반응형
반응형

[R] 도수분포표 (Frequency table), 분할표 (Contingency table) 만들기 - table(), prop.table(), xtabs(), margin.table()

 

 수천 명의 정보를 포함한 데이터를 한눈에 요약하고 싶을 때가 많다. 나이, 혈압과 같은 연속형 변수는 평균으로 요약하곤 하는데, 성별이나 음주 여부는 평균을 구할 수 없으니 빈도를 제시하곤 한다. 이를 표로 제시하면 도수분포표 (Frequency table)가 된다. 이를 넘어서 남성 중 음주자가 몇 명인지, 여성중 비음주자가 몇 명인지 알고 싶을 때가 있는데, 이때 사용하는 것이 분할표 (Contingency table)이다. 즉 본 글의 목적은 다음 두 개의 표 내용을 채우는 것이다.

 

<도수분포표>

  빈도 백분율 누적빈도 누적백분율
여성        
남성        

 

<분할표>

  비음주자 음주자 합계
여성      
남성      
합계      

 

R이 웬만한 프로그램보다 거의 모든 분야에서 분석하기엔 훨씬 편리하다. 하지만 오늘 다룰 도수분포표 및 분할표는 R이 압도적으로 불편하다. 그 불편한 분석을 오늘 해보고자 한다. (이런 이유로 CrossTable이라는 훌륭한 함수가 개발된 듯 하다. 다음 글로 소개하겠다. -2022.08.31 - [기술 통계/R] - [R] 도수분포표 (Frequency table), 분할표 (Contingency table) 만들기 - CrossTable())

 

*실습용 데이터는 아래 링크를 클릭하면 다운로드할 수 있습니다.

2022.08.04 - [공지사항 및 소개] - 분석용 데이터 (update 22.08.29)

 

분석용 데이터 (update 22.08.29)

2022년 08월 29일 버전입니다. 변수는 계속하여 추가될 예정입니다. 다음 카테고리에 있는 글에서 이용된 데이터입니다. - 기술 통계 - 통계 프로그램 사용 방법 1) 엑셀 파일 2) CSV 파일 3) 코드북

medistat.tistory.com

 

코드를 보여드리기에 앞서 워킹 디렉토리부터 지정하겠다.

워킹 디렉토리에 관한 설명은 다음 링크된 포스트에서 볼 수 있다.

2022.08.05 - [통계 프로그램 사용 방법/R] - [R] 작업 디렉토리 (Working Directory) 지정 - getwd(), setwd()

setwd("C:/Users/user/Documents/Tistory_blog")

 

데이터를 불러와 df에 객체로 저장하겠다.

데이터 불러오는 방법은 다음 링크에서 볼 수 있다.

2022.08.05 - [통계 프로그램 사용 방법/R] - [R] 데이터 불러오기 : EXCEL - read_excel(), read.xlsx()

2022.08.10 - [통계 프로그램 사용 방법/R] - [R] 데이터 저장하기 : CSV 파일 - write.csv(), write_csv()

2022.08.10 - [통계 프로그램 사용 방법/R] - [R] 데이터 불러오기 : SAS file (.sas7bdat) - read.sas7bdat(), read_sas()

install.packages("readr")
library("readr")
df<-read_csv("Data.csv")

 

도수분포표

코드 - table() 

* 변수: SEX (성별)

  -0: 여성

  -1: 남성

table(df$SEX)

table(df$SEX) :df데이터에 있는 SEX변수로 도수분포표를 만들어라.

 

결과

  0   1 
482 518

 

해석

SEX(성별)이 0(여성)인 사람이 482명, 1(남성)인 사람이 518명이다.

 

하지만 앞으로 table()함수는 사용하지 않을 것이다. 왜냐하면, 보면 알겠지만 어떤 변수를 분석한 것인지 표시되지 않는다. 한 개의 변수를 분석할 때에는 문제가 되지 않겠지만 당장 분석하게 될 분할표에서는 2개 이상의 변수가 들어가는데, 어떤 변수가 행에 들어갔는지, 열에 들어갔는지 표시되지 않으므로 헷갈릴 때가 있기 때문이다.

 

코드 - xtabs() 

xtabs(~SEX, data=df)

xtabs(~SEX, data=df) : df라는 데이터에 있는 SEX로 도수분포표를 만들어라. 단, 도수는 정해져 있지 않다. 

 

도수란 무엇인가?

만약 데이터가 다음과 같다면 도수가 있는 데이터라고 할 수 있다.

SEX(성별) ALCOHOL(음주) N(도수=몇 명인데?)
0 1 10
0 0 20
1 1 20
1 0 50

이 데이터는

여성 & 음주자: 10명

여성 & 비음주자: 20명

남성 & 음주자: 20명

남성 & 비음주자: 50명

임을 의미한다. 즉 각 특성을 갖는 사람이 몇 명인지 알려주는 것인데 이런 변수가 있다면 코드 xtabs(~SEX, data=df) ~왼쪽에 N을 적어야 한다.

 

#만약 도수를 나타내는 변수가 있는 자료였다면?
xtabs(N~SEX, data=df)

위 코드는 가상의 코드임으로 구동되지 않는다.

 

결과

SEX
  0   1 
482 518

함수 xtabs()는 정말 고맙게도 변수의 이름을 표기해준다.

 

표의 다음 파란 글씨를 이제 채울 수 있게 되었다.

  빈도 백분율 누적빈도 누적백분율
여성 482      
남성 518      

 

코드 - 분율

분율을 구하는 법은 다음과 같다.

prop.table(xtabs(~SEX, data=df))

prop.table(xtabs(~SEX, data=df)) :위에서 구한 도수분포표 [코드: xtabs(~SEX, data=df)]의 분율(proportion)을 구하라.

 

결과

SEX
    0     1 
0.482 0.518

SEX=0의 분율은 0.482, SEX=1의 분율은 0.518이다. 

하지만, %로 나타난 백분율이 아니므로 이대로는 표에 넣을 수 없다. 그리고 이런 식의 코드는 복잡함을 증대시키기 때문에 보통 다음과 같은 코드를 사용한다. 순서대로 설명하면 다음과 같다.

 

코드 - 백분율

freq_sex<-xtabs(~SEX, data=df)
prop_sex<-prop.table(freq_sex)
prop_sex_100<-100*prop_sex
prop_sex_100
round(prop_sex_100,digits=0)

freq_sex<-xtabs(~SEX, data=df) : 데이터 df안에 있는 변수 SEX의 도수분포표를 작성하여 freq_sex에 저장하라.

prop_sex<-prop.table(freq_sex)  : freq_sex의 분율을 구하여 prop_sex에 저장하라.
prop_sex_100<-100*prop_sex : prop_sex에 100을 곱하여 prop_sex_100에 저장하라

prop_sex_100 : prop_sex_100가 뭔지 보여달라.
round(prop_sex_100,digits=0) : prop_sex_100을 소수점 1번째 자리에서 반올림하여 정수로 보여달라

 

결과

SEX
   0    1 
48.2 51.8

SEX
 0  1 
48 52

위의 결과가 일반적인 백분율, 아래 결과는 정수로 반올림한 백분율을 나타낸다. 드디어 표의 두 번째 열을 채울 수 있게 되었다.

 

  빈도 백분율 누적빈도 누적백분율
여성 482 48.2    
남성 518 51.8    

 

코드 - 누적 빈도, 누적 백분율

#누적 빈도 구하기
cumsum(freq_sex)

#누적 백분율 구하기
cumsum(prop_sex_100)

cumsum(freq_sex) : freq_sex (도수분포표)의 누적 도수를 구하라.
cumsum(prop_sex_100) : prop_sex_100 (백분율)로 누적 백분율을 구하라.

 

결과

   0    1 
 482 1000 
 
     0     1 
 48.2 100.0

 

이제 표를 완성할 수 있게 되었다.

  빈도 백분율 누적빈도 누적백분율
여성 482 48.2 482 48.2
남성 518 51.8 1000 100.0

 

도수분포표 코드 전체

#작업 디렉토리 지정
setwd("C:/Users/user/Documents/Tistory_blog")

#데이터 불러오기
install.packages("readr")
library("readr")
df<-read_csv("Data.csv")

#도수분포표
freq_sex<-xtabs(~SEX, data=df) 
freq_sex                       #빈도 
prop_sex<-prop.table(freq_sex) 
prop_sex_100<-100*prop_sex
prop_sex_100                   #백분율
round(prop_sex_100,digits=0)
cumsum(freq_sex)               #누적 빈도
cumsum(prop_sex_100)           #누적 백분율

 

 

 

분할표

분할표를 작성해보자. 코드는 다음과 같다.

코드 - 빈도

#각 셀의 빈도 구하기
freq_sex_alc<-xtabs(~SEX+ALCOHOL, data=df)
freq_sex_alc

#행 별로 합친 빈도 구하기
freq_sex<-margin.table(freq_sex_alc, margin=1)
freq_sex

#열 별로 합친 빈도 구하기
freq_alc<-margin.table(freq_sex_alc, margin=2)
freq_alc

#전체 데이터 수 구하기
total_freq_sex_alc<-sum(freq_sex_alc) #혹은 sum(freq_sex)이나 sum(freq_alc)도 가능
total_freq_sex_alc

freq_sex_alc<-xtabs(~SEX+ALCOHOL, data=df) : ( '+' 표시 앞에 있는) SEX를 세로축에, ('+' 표시 뒤에 있는) ALCOHOL을 가로축에 넣고 분할표를 만들고 freq_sex_alc에 저장하라. 이때 데이터는 df를 사용하라.
freq_sex_alc : 만든 분할표를 보여달라.
freq_sex<-margin.table(freq_sex_alc, margin=1) :행 별로 합친 도수분포표 만들고 freq_sex에 저장하라. 즉, 성별의 도수분포표를 보여달라는 뜻이고 본 데이터에는 결측치가 없으므로 이는 "xtabs(~SEX, data=df)"와 같은 결과를 보여준다. (결측치가 있으면 결과가 다를 수 있다.)
freq_sex : 성별의 도수분포표를 보여달라.
freq_alc<-margin.table(freq_sex_alc, margin=2) :열 별로 합친 도수분포표 만들고 freq_alc에 저장하라. 즉, 음주 여부의 도수분포표를 보여달라는 뜻이고 본 데이터에는 결측치가 없으므로 이는 "xtabs(~ALCOHOL, data=df)"와 같은 결과를 보여준다. (결측치가 있으면 결과가 다를 수 있다.)
freq_alc : 음주 여부의 도수분포표를 보여달라.

total_freq_sex_alc<-sum(freq_sex_alc) : 빈도를 모두 더해 total_freq_sex_alc에 저장하라.
total_freq_sex_alc :총빈도수를 보여달라.

 

 

결과

   ALCOHOL
SEX   0   1
  0 236 246
  1 174 344
  
SEX
  0   1 
482 518 

ALCOHOL
  0   1 
410 590

[1] 1000

 

xtabs()함수의 진가는 분할표를 만들 때에 나온다. table()함수에는 나오지 않는 각 변수명을 보여주니 말이다. 위 데이터로 표의 빈도를 채울 수 있게 되었다.

빈도
백분율
행백분율
열백분율
비음주자 음주자 합계
여성 236 246 482
남성 174 344 518
합계 410 590 1000

 

코드 - 백분율

#각 셀의 백분율
prop_sex_alc<-prop.table(freq_sex_alc)
prop_sex_alc_100<-100*prop_sex_alc
prop_sex_alc_100

#행 별로 합친 데이터의 백분율
prop_sex<-prop.table(freq_sex)
prop_sex_100<-100*prop_sex
prop_sex_100

#열 별로 합친 데이터의 백분율
prop_alc<-prop.table(freq_alc)
prop_alc_100<-100*prop_alc
prop_alc_100

#전체 데이터의 백분율
prop_total<-prop.table(total_freq_sex_alc)
prop_total_100<-100*prop_total
prop_total_100

prop_sex_alc<-prop.table(freq_sex_alc) :2*2 분할표에서 각 셀의 분율을 구하고 prop_sex_alc에 저장하라
prop_sex_alc_100<-100*prop_sex_alc : 분율에 100을 곱하여 백분율을 구하고 prop_sex_alc_100에 저장하라
prop_sex_alc_100 : 백분율을 보여달라

 

prop_sex<-prop.table(freq_sex) :행 별로 합친 데이터의 분율을 구하고 prop_sex에 저장하라
prop_sex_100<-100*prop_sex : 분율에 100을 곱하여 백분율을 구하고 prop_sex_100에 저장하라
prop_sex_100 : 백분율을 보여달라

 

prop_alc<-prop.table(freq_sex) :열 별로 합친 데이터의 분율을 구하고 prop_alc에 저장하라
prop_alc_100<-100*prop_alc : 분율에 100을 곱하여 백분율을 구하고 prop_alc_100에 저장하라
prop_alc_100 : 백분율을 보여달라

 

prop_total<-prop.table(total_freq_sex_alc) : 전체 데이터를 합쳤을 때 분율을 구하고 prop_total에 저장하라
prop_total_100<-100*prop_total :분율에 100을 곱하여 백분율을 구하고 prop_total_100에 저장하라
prop_total_100 : 백분율을 보여달라

결과

   ALCOHOL
SEX    0    1
  0 23.6 24.6
  1 17.4 34.4
  
SEX
   0    1 
48.2 51.8 

ALCOHOL
 0  1 
41 59

[1] 100

표의 백분율을 채울 수 있게 되었다.

빈도
백분율
행백분율
열백분율
비음주자 음주자 합계
여성 236
23.6%
246
24.6%
482
48.2%
남성 174
17.4%
344
34.4%
518
51.8%
합계 410
41.0%
590
59.0%
1000
100.0%

백분율은 가로로 합하면 가로 합계의 백분율과 일치하고, 세로로 더하면 세로 합계의 백분율과 일치한다.

 

코드  - 행백분율

sum_row<-rowSums(freq_sex_alc)
prop_row<-freq_sex_alc/sum_row
prop_row_100<-100*prop_row
prop_row_100
round(prop_row_100, digits=2)

sum_row<-rowSums(freq_sex_alc) : 행 별로 더한 값을 sum_row에 저장한다. 즉 남성과 여성이 각각 몇 명이 있는지 보여준다. 이 값은 겉으로 보기엔 "freq_sex"와 같다. 하지만 속성이 약간 다르며 freq_sex로 대체할 수 없다.
prop_row<-freq_sex_alc/sum_row : 각 셀의 빈도를 행별로 더한 값으로 나눈다. 즉, 음주자건 비음주자건 남성이면 남성의 수로 나누고, 여성이면 여성의 수로 나눈다. 그리하여 분율을 구한다.
prop_row_100<-100*prop_row : 분율에 100을 곱해 백분율을 구한다. 
prop_row_100 : 백분율을 보여달라.

round(prop_row_100, digits=2) : 소수점 셋째 자리에서 반올림하여 둘째 자리까지만 표기하라.

 

결과

   ALCOHOL
SEX        0        1
  0 48.96266 51.03734
  1 33.59073 66.40927
  
   ALCOHOL
SEX     0     1
  0 48.96 51.04
  1 33.59 66.41

반올림한 결과가 훨씬 보기 편한 걸 알 수 있다. 그리고 가로로 합하면 100이 나오는 것을 볼 수 있다.

 

표의 행백분율을 채울 수 있게 되었다.

빈도
백분율
행백분율
열백분율
비음주자 음주자 합계
여성 236
23.6%
48.96%
246
24.6%
51.04%
482
48.2%
남성 174
17.4%
33.59%
344
34.4%
66.41%
518
51.8%
합계 410
41.0%
590
59.0%
1000
100.0%

 

코드 - 열백분율

R 특성상 조금 더 복잡해진다.

sum_col<-colSums(freq_sex_alc)
prop_col<-t(t(freq_sex_alc)/sum_col)
prop_col_100<-100*prop_col
prop_col_100
round(prop_col_100, digits=2)

sum_col<-colSums(freq_sex_alc) : 열 별로 더한 값을 sum_col에 저장한다. 즉 음주자와 비음주자가 각각 몇 명이 있는지 보여준다. 이 값은 겉으로 보기엔 "freq_alc"와 같다. 하지만 속성이 약간 다르며 freq_alc로 대체할 수 없다.
prop_col<-t(t(freq_sex_alc)/sum_col) : R에서 나눌 때에는 행 별로 나눈다. 즉 열 별로 나누려면 행/열을 바꾼 다음에 나누어야 한다. 어려운 말로 전치 행렬을 구해야 한다는 것이고 전치 행렬을 구하는 명령어가 t()다. 나눈 다음에 다시 한번 행/열을 바꾸지 않으면 세로에 음주 여부, 가로에 성별에 들어가 있으므로 보기에 편하려면 다시 한번 전치 행렬을 구해야 한다.
prop_col_100<-100*prop_col : 분율에 100을 곱해 백분율을 구한다. 
prop_col_100 : 백분율을 보여달라.
round(prop_col_100, digits=2) : 소수점 셋째 자리에서 반올림하여 둘째 자리까지만 표기하라.

 

결과

   ALCOHOL
SEX        0        1
  0 57.56098 41.69492
  1 42.43902 58.30508
  
   ALCOHOL
SEX     0     1
  0 57.56 41.69
  1 42.44 58.31

 

표를 완성할 수 있다.

빈도
백분율
행백분율
열백분율
비음주자 음주자 합계
여성 236
23.6%
48.96%
57.56%
246
24.6%
51.04%
41.69%

482
48.2%
남성 174
17.4%
33.59%
42.44%

344
34.4%
66.41%
58.31%

518
51.8%
합계 410
41.0%
590
59.0%
1000
100.0%

 

분할표 코드 전체

#작업 디렉토리 지정
setwd("C:/Users/user/Documents/Tistory_blog")

#데이터 불러오기
install.packages("readr")
library("readr")
df<-read_csv("Data.csv")

########빈도########

#각 셀의 빈도 구하기
freq_sex_alc<-xtabs(~SEX+ALCOHOL, data=df)
freq_sex_alc

#행 별로 합친 빈도 구하기
freq_sex<-margin.table(freq_sex_alc, margin=1)
freq_sex

#열 별로 합친 빈도 구하기
freq_alc<-margin.table(freq_sex_alc, margin=2)
freq_alc

#전체 데이터 수 구하기
total_freq_sex_alc<-sum(freq_sex_alc) #혹은 sum(freq_sex)이나 sum(freq_alc)도 가능
total_freq_sex_alc



########백분율########

#각 셀의 백분율
prop_sex_alc<-prop.table(freq_sex_alc)
prop_sex_alc_100<-100*prop_sex_alc
prop_sex_alc_100

#행 별로 합친 데이터의 백분율
prop_sex<-prop.table(freq_sex)
prop_sex_100<-100*prop_sex
prop_sex_100

#열 별로 합친 데이터의 백분율
prop_alc<-prop.table(freq_alc)
prop_alc_100<-100*prop_alc
prop_alc_100

#전체 데이터의 백분율
prop_total<-prop.table(total_freq_sex_alc)
prop_total_100<-100*prop_total
prop_total_100


########행백분율########

sum_row<-rowSums(freq_sex_alc)
prop_row<-freq_sex_alc/sum_row
prop_row_100<-100*prop_row
prop_row_100
round(prop_row_100, digits=2)


########열백분율########

sum_col<-colSums(freq_sex_alc)
prop_col<-t(t(freq_sex_alc)/sum_col)
prop_col_100<-100*prop_col
prop_col_100
round(prop_col_100, digits=2)

 

세 개 이상의 변수를 사용하는 분할표

코드

freq_sex_alc_htn<-xtabs(~SEX+ALCOHOL+HTN, data=df)
freq_sex_alc_htn

freq_sex_alc_htn<-xtabs(~SEX+ALCOHOL+HTN, data=df) : 데이터는 df를 사용하되 세로축에 SEX, 가로축에 ALCOHOL을 놓는다. HTN 값 별로 분할표를 각각 만들어 freq_sex_alc_htn에 저장한다.
freq_sex_alc_htn : 각각의 분할표를 보여달라.

 

결과

, , HTN = 0

   ALCOHOL
SEX   0   1
  0 114 122
  1  89 178

, , HTN = 1

   ALCOHOL
SEX   0   1
  0 122 124
  1  85 166

고혈압이 없는 (HTN=0) 사람들과 고혈압이 있는 (HTN=1) 사람들의 분할표를 각각 보여준다. 인구를 고혈압뿐만 아니라 RH혈액형으로도 나누고 싶다면 HTN뒤에 "+RH"를 붙여 다음과 같은 코드를 쓰면 된다.

 

#코드
freq_sex_alc_htn_rh<-xtabs(~SEX+ALCOHOL+HTN+RH, data=df)
freq_sex_alc_htn_rh

#결과
, , HTN = 0, RH = 0

   ALCOHOL
SEX   0   1
  0   0   0
  1   2   2

, , HTN = 1, RH = 0

   ALCOHOL
SEX   0   1
  0   1   0
  1   1   0

, , HTN = 0, RH = 1

   ALCOHOL
SEX   0   1
  0 114 122
  1  87 176

, , HTN = 1, RH = 1

   ALCOHOL
SEX   0   1
  0 121 124
  1  84 166

 

SAS에는 인구를 나누는 변수를 맨 앞에 쓰지만, R에서는 맨 뒤에 쓴다는 것을 유의해야 한다.

SAS에서의 분할표 작성법:

2022.08.18 - [기술 통계/SAS] - [SAS] 도수분포표 (Frequency table), 분할표 (Contingency table) 만들기 - PROC FREQ

 

[SAS] 도수분포표 (Frequency table), 분할표 (Contingency table) 만들기 - PROC FREQ

[SAS] 도수분포표 (Frequency table), 분할표 (Contingency table) 만들기 - PROC FREQ  수천 명의 정보를 포함한 데이터를 한눈에 요약하고 싶을 때가 많다. 나이, 혈압과 같은 연속형 변수는 평균으..

medistat.tistory.com

 

결론적으로 R로 분할표를 만드는 것은 매우 귀찮은 일이기 때문에 SPSS나 SAS를 쓰거나 CrossTable()함수를 쓰길 권한다.

2022.08.31 - [기술 통계/R] - [R] 도수분포표 (Frequency table), 분할표 (Contingency table) 만들기 - CrossTable()

 

[R] 도수분포표 (Frequency table), 분할표 (Contingency table) 만들기 정복 완료!

 

작성일: 2022.08.31.

최종 수정일: 2022.08.31.

이용 프로그램: R 4.1.3

RStudio v1.4.1717

RStudio 2021.09.1+372 "Ghost Orchid" Release 

운영체제: Windows 10, Mac OS 10.15.7

반응형
반응형

[SAS] 도수분포표 (Frequency table), 분할표 (Contingency table) 만들기 - PROC FREQ

 수천 명의 정보를 포함한 데이터를 한눈에 요약하고 싶을 때가 많다. 나이, 혈압과 같은 연속형 변수는 평균으로 요약하곤 하는데, 성별이나 음주 여부는 평균을 구할 수 없으니 빈도를 제시하곤 한다. 이를 표로 제시하면 도수분포표 (Frequency table)가 된다. 이를 넘어서 남성 중 음주자가 몇 명인지, 여성중 비음주자가 몇 명인지 알고 싶을 때가 있는데, 이때 사용하는 것이 분할표 (Contingency table)이다. 즉 본 글의 목적은 다음 두 개의 표 내용을 채우는 것이다.

 

<도수분포표>

  빈도 백분율 누적빈도 누적백분율
여성        
남성        

 

<분할표>

  비음주자 음주자 합계
여성      
남성      
합계      

 

*실습용 데이터는 아래 링크를 클릭하면 다운로드할 수 있습니다.

2022.08.04 - [공지사항 및 소개] - 분석용 데이터 (update 22.08.18)

 

분석용 데이터 (update 22.08.18)

2022년 08월 18일 버전입니다. 변수는 계속하여 추가될 예정입니다. 다음 카테고리에 있는 글에서 이용된 데이터입니다. - 기술 통계 - 통계 프로그램 사용 방법 1) 엑셀 파일 2) CSV 파일 3) 코드북

medistat.tistory.com

 

시작하기 위해 라이브러리를 만들고, 파일을 불러온다.

라이브러리 만드는 방법: 2022.08.05 - [통계 프로그램 사용 방법/SAS] - [SAS] 라이브러리 만들기 - LIBNAME

파일 불러오는 방법: 2022.08.05 - [통계 프로그램 사용 방법/SAS] - [SAS] 데이터 불러오기 및 저장하기 - PROC IMPORT, PROC EXPORT

 

*라이브러리 지정하기;
LIBNAME hong "C:/Users/User/Documents/Tistory_blog";

*파일 불러오기;
PROC IMPORT
DATAFILE="C:\Users\user\Documents\Tistory_blog\Data.xlsx"
DBMS=EXCEL
OUT=hong.df
REPLACE;
RUN;

 

코드

성별과 음주 여부의 분할표를 만드는 코드는 다음과 같다.

-변수

 1) SEX: 성별

  -0: 여성

  -1: 남성

 2) ALCOHOL: 음주 여부

  -0: 비음주자

  -1: 음주자

 

 

도수분포표 

PROC FREQ DATA=hong.df; 
TABLE SEX;
RUN;

PROC FREQ DATA=hong.df; : 도수분포표를 구하는 코드를 시작하며, 데이터는 hong 라이브러리 내의 df 파일을 사용한다.
TABLE SEX; : SEX의 도수분포표를 구하라

결과

 위 결과에 숫자가 너무 많아 지저분해 보이고, 한눈에 잘 들어오지 않을 수 있다. 그런 경우 다음과 같은 옵션을 통해 표시되는 숫자들을 제어할 수 있다.

 NOPERCENT: 백분율 표시 안 함

 NOCUM: 누적 빈도 및 누적 백분율 표시 안 함

PROC FREQ DATA=hong.df; 
TABLE SEX/ NOCUM ;
RUN;

결과

분할표 

PROC FREQ DATA=hong.df; 
TABLE SEX*ALCOHOL;
RUN;

PROC FREQ DATA=hong.df; : 분할표를 구하는 코드를 시작하며, 데이터는 hong 라이브러리 내의 df 파일을 사용한다.
TABLE SEX*ALCOHOL; : SEX와 ALCOHOL 변수로 분할표를 만들어라.

 - *표시 앞에 오는 변수가 세로축에, 뒤에 오는 변수가 가로축에 놓이게 된다.

결과

각 셀 안의 내용물은 다음과 같다

(1) 빈도 - 각 셀에 해당하는 인구의 수

  비음주자 음주자 합계
여성 236
23.60
48.96
57.56
246
24.60
51.04
41.69
482
48.20
남성 174
17.40
33.59
42.44
344
34.40
66.41
58.31
518
51.80
합계 410
41.00
590
59.00
1000
100.00

 

(2) 백분율 - 빈도를 전체 인구 (1,000)으로 나눠 %로 나타낸 값

세로 혹은 가로로 더하면 합계의 백분율과 일치하며 백분율의 총합은 100과 같다.

  비음주자 음주자 합계
여성 236
23.60
48.96
57.56
246
24.60
51.04
41.69
482
48.20
남성 174
17.40
33.59
42.44
344
34.40
66.41
58.31
518
51.80
합계 410
41.00
590
59.00
1000
100.00

 

(3) 행 백분율 - 각 행에서 빈도가 차지하는 분율.

 - 여성에서 비음주자가 차지하는 분율은 48.96%, 음주자가 차지하는 분율은 51.04%다.

 - 남성에서 비음주자가 차지하는 분율은 33.59%, 음주자가 차지하는 분율은 66.41%다.

따라서 행별로 더하면 (=같은 색깔끼리 더하면) 100%가 나오게 된다.

  비음주자 음주자 합계
여성 236
23.60
48.96
57.56
246
24.60
51.04
41.69
482
48.20
남성 174
17.40
33.59
42.44
344
34.40
66.41
58.31
518
51.80
합계 410
41.00
590
59.00
1000
100.00

 

(4) 칼럼 백분율 - 각 열(칼럼)에서 빈도가 차지하는 분율.

 - 비음주자에서 여성이 차지하는 분율은 57.56%, 남성이 차지하는 분율은 42.44%다.

 - 음주자에서 여성이 차지하는 분율은 41.69%, 남성이 차지하는 분율은 58.31%다.

따라서 열(칼럼) 별로 더하면 (=같은 색깔끼리 더하면) 100%가 나오게 된다.

  비음주자 음주자 합계
여성 236
23.60
48.96
57.56
246
24.60
51.04
41.69
482
48.20
남성 174
17.40
33.59
42.44
344
34.40
66.41
58.31
518
51.80
합계 410
41.00
590
59.00
1000
100.00

 

 

 

 위 결과에 숫자가 너무 많아 지저분해 보이고, 한눈에 잘 들어오지 않을 수 있다. 그런 경우 다음과 같은 옵션을 통해 표시되는 숫자들을 제어할 수 있다.

 NOFREQ: 빈도 표시 안 함 

 NOPERCENT: 백분율 표시 안 함

 NOROW: 행 백분율 표시 안 함

 NOCOL: 열(칼럼) 백분율 표시 안 함

 

PROC FREQ DATA=hong.df; 
TABLE SEX*ALCOHOL / NOPERCENT NOROW NOCOL;
RUN;

결과

PROC FREQ DATA=hong.df; 
TABLE SEX*ALCOHOL / NOPERCENT NOCOL;
RUN;

결과

PROC FREQ DATA=hong.df; 
TABLE SEX*ALCOHOL / NOFREQ NOPERCENT NOCOL;
RUN;

결과

 

세 개 이상의 변수를 사용하는 분할표

세 개 이상의 변수를 사용하여 분할표를 작성하고 싶을 때가 있다. 다음 두 경우를 생각해보도록 하겠다.

1) 두 가지의 분할표를 작성하는 경우

:성별-음주의 분할표와 성별-고혈압의 분할표를 각각 그리고자 할 때

*방법 1: TABLE 구문 안에 원하는 변수의 조합을 모두 쓴다;
PROC FREQ DATA=hong.df; 
TABLE SEX*ALCOHOL SEX*HTN;
RUN;

*방법 2: 공통변수로 묶은 뒤 괄호 안에 나머지 변수를 띄어쓰기로 구분하여 작성한다;
PROC FREQ DATA=hong.df; 
TABLE SEX*(ALCOHOL HTN);
RUN;

두 개의 코드는 완벽히 똑같은 결과를 제시해준다. 

결과

2) 조건에 따라 분할표를 작성하는 경우

:고혈압 여부에 따른 성별-음주의 분할표를 그리고자 할 때

PROC FREQ DATA=hong.df; 
TABLE HTN*SEX*ALCOHOL;
RUN;

문제 상황처럼 고혈압 여부(HTN)에 따른 성별(SEX)과 음주(ALCOHOL)의 분할표를 그리고자 한다면, 고혈압 여부(HTN)를 TABLE구문 맨 앞에 추가로 붙여준다. 시행하면 다음과 같은 결과를 얻는다.

결과

고혈압이 없는 (HTN=0) 사람의 성별-음주 분할표가 위에 나오고, 고혈압이 있는 (HTN=1) 사람의 성별-음주 분할표가 따라 나오게 된다. 

 - SAS를 조금 아는 사람이라면 "WHERE 구문을 쓰면 되는데 왜 이렇게 복잡하게 하냐?"라고 이야기할 수도 있지만, 국민건강 영양조사(NHANES, KNHANES) 자료를 쓸 때엔 WHERE 구문이나 BY 구문의 사용이 엄격하게 금지되므로 이 방법이 필수적이다. 물론 이땐 PROC FREQ이 아니라 PROC SURVEYFREQ을 사용하게 된다.

 - SAS에는 인구를 나누는 변수를 맨 앞에 쓰지만, R에서는 맨 뒤에 쓴다는 것을 유의해야 한다.

 

SAS 도수분포표, 분할표 정복 완료!

 

작성일: 2022.08.18.

최종 수정일: 2022.08.31.

이용 프로그램: SAS v9.4

운영체제: Windows 10

반응형
반응형

[SPSS] 고급 Q-Q Plot - Van der Waerden, Rankit, Tukey, Blom

다음 글을 읽고 와야 이해하기 편하므로 먼저 읽고 올 것을 권한다.

2022.08.12 - [통계 이론] - [이론] Q-Q Plot (Quantile-Quantile Plot)

 

[이론] Q-Q Plot (Quantile-Quantile Plot)

[이론] Q-Q Plot (Quantile-Quantile Plot) 정규성을 검정할 때 Q-Q Plot을 쓰곤 한다. 그런데 이런 궁금증이 들 수 있다. 왜 Q-Q Plot이 직선에 가까운 것이 정규성을 따른다는 뜻인가? 이에 대해 조목조목..

medistat.tistory.com

 

Q-Q Plot의 이론에서 상대적 위치를 대칭적으로 정하는 방법이 여럿 있다고 언급했다. 본 글에서는 특정 방법을 지정하여 Q-Q Plot을 그리는 법에 대해 소개하겠다.

 

*실습용 데이터는 아래 링크를 클릭하면 다운로드할 수 있습니다.

2022.08.04 - [공지사항 및 소개] - 분석용 데이터 (update 22.08.29)

 

분석용 데이터 (update 22.08.29)

2022년 08월 29일 버전입니다. 변수는 계속하여 추가될 예정입니다. 다음 카테고리에 있는 글에서 이용된 데이터입니다. - 기술 통계 - 통계 프로그램 사용 방법 1) 엑셀 파일 2) CSV 파일 3) 코드북

medistat.tistory.com

 

데이터를 불러오도록 하겠다. 데이터를 불러오는 방법은 다음 링크에서 확인할 수 있다.

2022.08.04 - [통계 프로그램 사용 방법/SPSS] - [SPSS] 데이터 불러오기 및 저장하기

 

 

1) 분석(A) > 기술통계량(E) > Q-Q 도표...

 

2) 분석하고자 하는 변수 (ALT)를 오른쪽으로 넘긴다.

 

*검정분포(T), 분포모수, 변환은, 등순위에 부여되는 순위의 설정은 변경하지 않는다.

 

3)비율추정 공식에서 원하는 방식을 선택한다.

 

 

결과

1) Van der Waerden

2) Rankit

3) Tukey

4) Blom

 지금까지의 결과를 보면 알겠지만, 그림의 차이를 찾아볼 수 없을 정도로 거의 동일하다. 이렇게 $수가 충분하면 어떤 방법을 고르든 거의 똑같은 결과를 내주므로 적용할 방법에 대해 크게 연연할 필요가 없다.

 

[SPSS] 고급 Q-Q Plot 정복 완료!

 

작성일: 2022.08.18.

최종 수정일: 2022.09.06.

이용 프로그램: IBM SPSS v26

운영체제: Windows 10

반응형

+ Recent posts