통계

[통계 데이터분석] 데이터 요약- 범주형 변수 (기술통계 관점) ⭕

mming_10 2024. 9. 22. 14:23

빈도표 (table 함수)

: 데이터의 대략적인 분포를 손쉽게 파악 가능

: 범주별 출현 빈도를 나타내는 요약표를 얻을 수 있음

: 최빈값 (mode)은 가장 높은 빈도를 갖는 변수값

 

교차표

: 두 변수의 범주별 조합 빈도를 조사하여 작성한 2차원의 테이블

: 두 범주형 변수 간의 관계를 파악하고자 할 때 유용

 

1. 데이터 요약- 범주형 변수

library(MASS)
#survey 데이터셋 사용
str(survey)

# 응답자의 흡연 습관, 범주화
levels(survey$Smoke)

 

-> Smoke 변수는 'factor 데이터 구조' (범주형 데이터)/ 4 level

 

-> table( ) 함수를 이용해서 Smoke 변수에 대한 '네 가지 레벨 빈도'를 구할 수 있음

frqtab <- table(survey$Smoke) #frqtab 이라는 변수에 빈도 저장
frqtab
class(frqtab) #table객체 반환
frqtab[2] #두 번쨰 범주에 대응되는 값 출력됨

-> table 객체는 '배열, 행렬과 동일한 데이터 구조'를 갖음!

-> 배열에서와 마찬가지로 인덱스 나 이름을 이용해서, 특정 원소를 선택할 수 있음


1-1) 범주형 변수 -> 최빈값(가장 높은 빈도) 이용!

 

# max() 함수 이용하여 '최빈값' 파악하기!

frqtab== max(frqtab) #TRUE 에 해당하는 것= 최빈 범주!
frqtab[frqtab== max(frqtab)] #TRUE 에 해당하는 범주의 변수값 추출 가능!
names(frqtab[frqtab== max(frqtab)]) #해당 범주의 이름만 추출

- 최빈값 위치를 인덱스로 반환

# which.max() 함수 = 주어진 벡터의 최빈값 위치를 인덱스로 반환

# which.max()의 인수: 빈도표 지정
which.max(frqtab)

#생성한 빈도표의 벡터에다가 인덱스로 주게 되면 '두번째 위치에 있는 범주' 출력
# frqtab[2] 값이랑 같음
frqtab[which.max(frqtab)] 
names(frqtab[which.max(frqtab)])

- 빈도에 대해서 비율 구하기

# prop.table( ) 함수 =  빈도가 비율로 환산되는 함수

#prop.table()의 인수= 빈도표 지정
frqtab.prop <- prop.table(frqtab)
frqtab.prop # 네 개의 범주의 비율 추출
frqtab.prop["Never"] #특정 범주만의 비율 추출
frqtab.prop * 100 #백분율로 환산

-> 특정 값이 출현하는 비율을 알고자 할 때, 논리연산 이용! (논리값 TRUE:1/ FALSE:0 변환)

-> 논리값을 이용하여, 특정 값의 출현 여부를 먼저 식별한 다음, mean( )함수로 평균 구하기 [상대적 빈도, 비율]

(비흡연자에 대해서 MEAN 구하기)

#1. '비흡연자'에 대해 논리연산 식별
survey$Smoke== "Never" #TRUE: 비흡연자/ FALSE: 흡연자

#평균값은 'TRUE'인 값의 비율을 의미하고, 이는 [비흡연자의 비율]이 됨
mean(survey$Smoke== "Never") #결측값 존재시, NA 가 출력됨
mean(survey$Smoke== "Never", na.rm= TRUE)

 

=> 80% 정도가 '담배를 피우지 않는 사람'의 비율


  • anorexia 데이터셋 이용= 식욕부진증 환자의 '치료 전'과 '치료 후'의 몸무게 기록 데이터셋
head(anorexia)

( 치료 전_Prewt, 치료 후 몸무게_Postwt 변수 비교!)

- 치료 후 몸무게가 증가한 식욕부진증 환자의 비율 구하기 (mean)

#치료 후 몸무게가 증가한 식욕부진증 환자-> 논리연산
anorexia$Postwt > anorexia$Prewt # TRUE: 치료 후 몸무게 증가
mean(anorexia$Postwt > anorexia$Prewt)


  • mammals 데이터셋 이용 = 동물들의 두뇌 무게와 몸무게가 저장된 데이터셋

- 편차 계산 (값- 평균)

- 편차의 절댓값 이 표준편차 보다 큰 경우

 

- 두뇌의 무게가 몸무게보다 상대적으로 매우 크거나, 매우 작은 동물 식별

= 두뇌의 무게가 평균으로부터 두 개의 표준편차보다 큰 동물의 비율 계산

#각 동물별로 두뇌 무게의 평균과의 편차 계산 
mammals$brain - mean(mammals$brain) 

# 절댓값으로 계산 ('차이'에 집중= 양수,음수 포함!)=> 절댓값 편차 > 표준편차
# 두뇌의 무게가 평균으로부터 두 개의 표준편차보다 큰 동물= TRUE
abs(mammals$brain - mean(mammals$brain)) > 2*sd(mammals$brain - mean(mammals$brain))
mean(abs(mammals$brain - mean(mammals$brain)) > 2*sd(mammals$brain - mean(mammals$brain)))

=> 두뇌의 무게가 상대적으로 매우 크거나 작은 동물 = 3%


  • SP500 데이터셋 이용 = SP500 지수 수익률이 일자별로 저장되어 있음

 

- SP500 수익률이 전날보다 증가한 비율 계산 = 연속된 두 날짜의 수익률의 차이가 0보다 큰 일자의 비율을 계산

- diff( ) = 주어진 벡터로부터 연속된 두 숫자의 차이 계산 함수

diff(SP500) #연속된 두 일자 간의 차이 계산
diff(SP500) > 0 #수익률이 전일보다 증가한 경우
mean(diff(SP500) > 0 #TRUE 에 해당되는 날짜의 비율을 계산 가능


- 빈도표를 이용하여 '변수의 범주 별 빈도'를 파악하면,  개별 변수의 범주 별 분포를 대략적으로 이해할 수 있음
- 두 변수의 범주 조합에 따른 조합 별 빈도를 살펴보면,  두 변수 간의 관계를 이해하는 데 도움이 됨

- 교차표는 두 변수의 범주별 조합 빈도수를 조사해 작성한 2차원의 테이블을 의미

* 교차표 (두 범주형 변수 간의 관계를 파악하고자 할 때 유용하게 활용할 수 있음)*


  • Arthritics 데이터셋 이용 ( 루마티스 관절염 치료제 효능에 대한 실험 데이터 )
install.packages("vcd")
library(vcd)
str(Arthritis)

# Arthritics 데이터셋은 다섯 개의 변수로 구성 되어 있음 = ID/ Treatment/ Sex/ Age/ Improved
# Treatment 변수 = 치료제 <- 범주형 변수 (펙터)
# Improved 변수 = 치료효과 <- 범주형 변수 (펙터)

 

levels(Arthritis$Treatment)
levels(Arthritis$Improved)

# Treatment 변수= 위약 투약을 나타내는 'Placebo'/ 신약 투약을 나타내는 'Treated', 두 개의 레벨로 저장

# Improved 변수= 각 처치에 따른 치료 효과

 

 

1-2) 범주형 변수 교차표 만들기 - [Treatment 와 Improved 변수 간의 교차표]

  • table () 함수 이용 <- 이 함수에 두 개의 범주형 변수를 차례로 지정하게 되면 각각 행과 열로 배치가 되는 교차표가 생성됨
crosstab <- table(Arthritis$Improved, Arthritis$Treatment)
crosstab

# table() 함수의 첫 번째 인수는 행 변수를 나타내고, 두 번째 인수는 열 변수를 나타냄
  -> 행에는 Improved 변수의 범주들이 배치되고, 열에는 Treatment 변수의 범주
# 셀 값은 '대응되는 두 개의 범주가 교차하는 빈도수를 의미함'
  -> '21' 이란 숫자는 '신약을 투입한 환자들 가운데서 증상 개선 효과가 Marked(현저하게) 좋아진 환자의 수를 의미함

 

# 교차표는 행렬과 같은 형태로 출력이 되기 때문에 '행렬형 인덱스'를 이용해서 특정 셀 값을 추출할 수 있음
   : 행과 열에 있는 범주를 콤마(,)를 중심으로 -> 대응되는 셀값을 추출할 수 있음

crosstab["Marked", "Treated"]
table(Arthritis$Improved, Arthritis$Treatment)
crosstab["Marked", "Treated"]
table(Arthritis$Improved, Arthritis$Treatment,
      dnn= c("Improved", "Treatment")) #dnn 인수에 '행과 열 이름 지정'

 

  •  xtabs()함수 이용 가능 = 교차표 생성 가능 함수.2 (기본적으로, 행과 열의 이름이 같이 출력되는 결과 추출)
    -> formula 인터페이스 방식으로 행과 열의 변수를 지정/ formula 의 오른쪽에 '행의 변수와 열의 변수를 +로 연결해서 지정
  • -> 행과 열의 이름이 함께 출력됨 (Improved, Treatment )
crosstab <- xtabs(~ Improved + Treatment,data= Arthritis)
crosstab

 

# ~(tilde)의 오른쪽에 행의 변수와 열의 변수를 차례대로 + 로 연결해서 지정

 

- 교차표 생성 시, 교차표의 행과 열에 대한 빈도 합 계산 가능 (margin.table() 함수 이용)

  • margin.table() 함수의 첫 번째 인수 = 교차표를 지정
  • margin.table() 함수의 두 번째 인수 = margin 인수 지정 

# margin= ) 1을 지정하면 행의합/ 2를 지정하면 열의 합

margin.table(crosstab, margin = 1)
margin.table(crosstab, margin = 2)

 

  • prop.table() -> 행의 비율과 열의 비율을 산출할 수 있음

# margin 인수에 1을 지정한 prop.table()함수를 실행하게 되면, 

# 'margin= 1' -> 행이 100%인 비율의 교차표 (행의 합이 1)가 만들어짐  = Improved 의 세 개의 범주별로 각 범주 합이 100%

# 'margin=2' -> 열이 100%인 비율의 교차표 (열의 합이 1)가 만들어짐 = Treatment 의 두 개의 범주별로 각 범주 합이 100%

 

# 열의 비율의 교차표를 보면, Treatment 변수의 Treated 범주의 Marked

  = 신약이 투입된 환자에 대해서 증상 개선 효과가 '현저하게 호전된 환자'의 비율 51.2%라는 걸 확인 가능
# 반면에, 위약이 투입된 경우 'Placebo 범주에 대응되는 환자' 가운데 16.2 % 만이 Marked 수준의 현저한 증상 개선 효과를 보임

 

[열의 방향으로 100% 만드는 것의 중요성] - 표에 대한 설명
- 정보 전달의 내용이 달라질 수도 -> 순서 의미있게 배치해야 함!(원인:열, 결과:행)
-> 열의 비율을 계산하면 설명하기 쉬움!
    원인)치료약 -> 결과)치료결과
-> 예- [성별에 따른 선호 음식: 성별(원인) -> 선호음식 (결과)]

 

- 교차표상의 개별 셀의 비율을 계산

  • prop.table()함수의 margin 인수에 아무것도 지정하지 않고 교차표만을 지정하면 됨
prop.table(crosstab)

  • addmargins() 함수 이용: 교차표의 행과 열의 빈도합을 포함시키기
addmargins(crosstab, margin=1)
addmargins(crosstab, margin=2)


# margin=1, 행의 값들을 모두 합한 '합계 행'을 의미
# margin=2, 열의 값들을 모두 합한 '합의 열'을 의미


- addmargins() 함수에 crosstab 교차표만을 지정하고, margin 인수를 지정하지 않으면 두 변수 모두에 대한 합의 행과 열을 구함

addmargins(crosstab)



# 100%를 나타내는 열과 행을 생성해서 교차표 해석에 도움을 줌

 

- addmargins(prop.table())

- 행과 열의 비율이 100%가 되는 '행 혹은 열의 비율의 교차표'를 만들었을 경우엔, 합계가 100%가 된다는 것을 보여줌

addmargins(prop.table(crosstab, margin=2), 1)
addmargins(prop.table(crosstab, margin=1), 2)

 

  • 교차표 생성 -> table(), xtabs(), gmodels 패키지에 포함된 CrossTable() 함수 이용
install.packages("gmodels")
library(gmodels)
# CrossTable의 첫번째 인수= 교차표 상의 행에 배치될 변수 지정
# CrossTable의 두번째 인수= 교차표 상의 열에 배치될 변수 지정
# CrossTable 함수는 많은 인수들을 제공함. 
# -> 인수 지정을 통해서 '교차표에 포함될 정보를 선택할 수 있음' or '불필요한 정보는 표시 안 되게 할 수 있음'
# -> 'chisq 톨계량 값은 필요가 없기 때문에 'FALSE'
# -> dnn 인수 지정을 통해 '교차표의행과 열에 표시될 이름'지정 

CrossTable(Arthritis$Improved, Arthritis$Treatment,  prop.chisq= FALSE,
           dnn= c("Improved", "Treatment" ))

오른쪽이 'prop.chisq= FALSE'

# CrossTable() 첫번째 인수에 교차표상의 행에 배치될 변수를 지정, 두번째 인수에 열에 배치될 변수를 지정함
  -> 인수 지정을 통해서 '교차표에 포함될 정보'를 선택할 수 있음
  -> 때로는, 불필요한 정보를 또 표시가 안 되도록 지정할 수 있음
(예, chisq(카이스퀘어어)통계량 값은 필요가 없기 때문에, prop.chisq= FALSE 로 지정하여 표시가 되지 않도록 함)
# dnn 인수 지정을 통해서 '교차표의 행과 열에 표시될 행, 열의 이름을 지정'

1) 셀의 관측값의 개수, 2) 행의 비율, 3) 열의 비율,  4) 전체 셀의 비율

 

1-3) 범주형 변수가 세 개 이상 시- 다차원 테이블 생성
# 2차원 테이블 생성- table(), xtabs() 함수 모두 다차원 테이블 생성 가능

multtab <- table(Arthritis$Improved, Arthritis$Sex, Arthritis$Treatment)
multtab

 

# 차원이 3개 있을 경우- 첫 번째 차원을 행/ 두번째 차원- 열/ 세번째 차원- 테이블
   -> 다차원일 경우, 배열에서는 테이블별로 행렬을 하나씩 출력

 

# 세번째 차원에 있던 Treatment의 두 개의 범주별로 Improved, Sex 변수를, 행과 열로 하는 교차표 만들기

multtab <- xtabs(~ Improved + Sex + Treatment, data= Arthritis)
multtab

  • ftable() 함수 이용 -  더 단순하고, 보기 좋은 형태로 출력 가능 
# ftable() 함수의 인수= xtabs() 함수나 table() 함수로부터 생성한 다차원 테이블을 지정
ftable(multtab)

# ftable() 함수를 이용하게 되면, 행과 열에 들어갈 변수를 지정함

  -> 행에 1차원과 2차원에 지정된 범주형 변수가 배치됨,
  -> 열에 3차원에 지정된 범주형 변수가 배치됨

ftable(multtab, row.vars= c(2,3))

#'row.vars' 인수= 두번째 차원(Sex 변수)과 세번째 차원(Treatment 변수)을 행에 배치
   -> Sex 변수와 Treatment 변수가 행에 배치되는 교차표 생성/ 지정되지 않은 첫번째 차원(Improved 변수가)은 열로 배치됨

ftable(multtab, row.vars= c(2,3), col.vars)



# ftable() 함수는 table 객체를 인수로 받을 수도 있지만, 데이터프레임으로부터 직접 테이블을 생성할 수도 있음
# ftable() 함수에 필요한 열을 포함하고 있는 데이터프레임 지정

# ftable() 함수의 첫번째 인수= 필요한 열(세 개)을 포함하고 있는 데이터프레임 지정
# ftable() 함수의 두번째 인수(row.vars 인수)= 행으로 배치될 변수를 지정
 
ftable(Arthritis[c("Improved","Sex","Treatment")],
       row.vars= c(2,3))

 

-> margin.table( )함수 = 3차원 이상으로 확장 가능! 

# multab <- xtabs(~ Improved + Sex + Treatment, data= Arthristis)
# -> Improved(차원 1), Sex(차원 2), Treatment(차원 3) 
# margin.table()함수의 margin인수 = 세 개의 차원 지정(multab)

margin.table(multtab, 1) 
# -> '1'지정하면, 차원 1인 'Improved' 변수에 의한 빈도합 계산
margin.table(multtab, 2)
# -> '2'지정하면, 차원 2인 'Sex' 변수에 의한 빈도합 계산
margin.table(multtab, 3)
# -> '3'지정하면, 차원 2인 'Treatment' 변수에 의한 빈도합 계산

-> 복수의 차원을 지정해서, 복수의 차원에서 만들어지는 교차 셀에 대한 빈도합도 출력 가능!

margin.table(multtab, c(1,3))

# 첫번째 차원과 세번째 차원이 이루는 교차 셀에 대한 빈도합을 출력
  -> 첫번째: Improved, 세번째: Treatment (이 두개의 차원에서 만들어지는 교차셀의 빈도합 계산)
# 이때, 인덱스로 주어지지 않은 두번째 차원인 Sex에 대해서 합산이 이루어짐
성별과 무관하게 두 개의 차원에서 만들어지는 교차셀의 빈도합 출력 가능
# 복수의 차원을 인수로 지정하게 되면, 변수들 간의 관계를 보여주는 유용한 교차표 생성가능
  (예: 성별과 치료제의 조합에 따라서 치료효과의 차이가 있는지를 보여주는 교차표 생성 가능)

# margin 인수에 '성별 차원'과 '치료제 차원'을 지정해서 두 개의 교차셀에서 만들어지는 비율 출력

# 성별이 2차원, 치료제가 3차원
ftable(prop.table(multab, c(2,3))

-> 신약을 처방받은 여성 가운데서 59.2% 는 현저한 증상 개선 효과를 보이고 있는 반면에, 

신약을 처방받은 남성 가운데는 35.7% 만이 현저한 증상 개선 효과를 보이는 것을 볼 수 있음

-> 교차표 => 신약의 처방 효과가 남성보다는 여성한테서 더 잘 나타남을 확인 가능!


자료출처:

https://www.youtube.com/watch?v=3qQM4xgHPic&list=PLY0OaF78qqGAxKX91WuRigHpwBU0C2SB_&index=3