2.6 요인(factor)과 테이블(table)
- 요인(factor) 데이터 타입은 통계학에서 범주형 변수(categorical variable)을 표현하기 위한 R의 데이터 타입으로 범주형 자료는 크게 명목형(nominal)과 순서형(ordinal) 으로 구분
- 테이블(table) 객체는 factor 객체에 대한 빈도를 나타내기 위해 사용
범주형 자료
- 데이터가 사전에 정해진 특정 유형으로만 분류되는 경우: 성별, 인종, 혈액형 등
- 범주형 자료는 명목형과 순서형으로 구분 가능
- 순서형 자료 예: 성적, 교육수준, 선호도, 중증도 등
2.6.1 요인(factor)
- 범주형 자료를 표현하기 위한 R의 객체 클래스
- Factor는 정수형 벡터를 기반으로 levels (수준) 이라는 속성이 추가된 객체임
- 숫자 또는 문자로 표현 되었다 하더라도 범주형으로 이해
- Factor는 level에 해당하는 값만 가질 수 있는 벡터로 간주
- Factor 생성 함수
# factor 정의 함수
factor(data, # factor로 표현하고자 하는 값. 주로 문자형
levels, # 요인의 수준, 미리 정한 값
labels, # 수준에 대한 레이블링
ordered # 순서형 자료 표시 여부
# TRUE/FALSE, default = FALSE
)
- 수치형을 factor로 만들어도 처음 입력 값은 문자형으로 변하고 level 값으로 치환
- 대신 (1, 2, 3)이 중심값이 됨 \(\rightarrow\) 정수형 벡터임
[1] "integer"
$levels
[1] "4" "5" "6"
$class
[1] "factor"
Factor w/ 3 levels "4","5","6": 1 1 1 1 2 2 2 2 3 3 ...
[1] "4" "5" "6"
[1] 3
- Factor를 벡터 결합 함수
c()
로 결합
[1] 1 1 1 1 2 2 2 2 3 3 3 3 1
- Factor의 범주 수준(level) 및 범주명(label) 지정
[1] 1 1 1 1 2 2 2 2
Levels: 1 2
# factor의 범주 수준 및 범주 명칭 지정
sex <- factor(x, levels = 1:2, labels = c("male", "female"))
sex # level의 값이 명칭으로 변경
[1] male male male male female female female female
Levels: male female
Factor w/ 2 levels "male","female": 1 1 1 1 2 2 2 2
# 값은 존재하지 않으나 수준을 미리 정해 놓은 경우
severity <- factor(1:2, levels = c(1, 2, 3), labels = c("Mild", "Moderate", "Severe"))
severity[2] <- "Severe"
# 존재하지 않는 수준 할당
severity[1] <- "Good"
Warning in `[<-.factor`(`*tmp*`, 1, value = "Good"): 요인의 수준(factor level)이
올바르지 않아 NA가 생성되었습니다.
[1] <NA> Severe
Levels: Mild Moderate Severe
- 순서형 factor 생성
severity <- factor(rep(1:3, times = 3), levels = 1:3,
labels = c("Mild", "Moderate", "Severe"),
ordered = T)
severity
[1] Mild Moderate Severe Mild Moderate Severe Mild Moderate
[9] Severe
Levels: Mild < Moderate < Severe
[1] TRUE
요인형 객체에 적용되는 일반적인 함수
tapply()
함수
- 특정 요인 수준의 고유한 조합으로 각 그룹에 속한 값에 특정 함수를 적용한 결과를 반환
- 일반적인 함수 사용 형태는 아래와 같음
- 예시: 2020년 4월 15일 총선의 연령별 지지율
# 문자열을 INDEX의 인수로 받은 경우
x <- c(48, 43, 27, 52, 38,
67, 23, 58, 72, 85) # 유권자 연령
f <- rep(c("더불어민주당", "미래통합당"), each = 5)
t <- tapply(x, f, mean) # f의 요인 수준 별 x (연령) 평균 계산
t
더불어민주당 미래통합당
41.6 61.0
# x, f 순서를 랜덤하게 섞은 다음 결과
set.seed(12345) # 난수 생성 결과 고정
idx <- order(runif(10))
x <- x[idx]
f <- f[idx]
tapply(x, f, mean)
더불어민주당 미래통합당
41.6 61.0
- Factor가 2개 이상인 경우 두 factor 객체의 수준의 조합(AND 조건)에 따른 그룹을 만든 후 그룹별 함수 적용
s <- rep(c("M","F"), each = 6)
income <- c(35, 42, 68, 29, 85, 55,
30, 40, 63, 27, 83, 52) * 100 # 단위: 만원
age <- c(32, 36, 44, 25, 55, 41,
28, 33, 46, 23, 54, 44)
set.seed(12345) # 난수 생성 결과 고정
idx <- order(runif(12))
s <- s[idx]; income <- income[idx]; age <- age[idx]
# age <= 40 -> 1, 40 < age <= 50 -> 2,
# age >= 50 -> 3 할당: ifelse() 함수 사용
age <- ifelse(age <= 40, 1,
ifelse(age <= 50, 2, 3))
tapply(income, list(sex = s, age = age), mean)
age
sex 1 2 3
F 3233.333 5750 8300
M 3533.333 6150 8500
R에서 가장 많이 활용되는 함수 계열 중 하나로 *apply()
를 들 수 있다. 벡터, 행렬 등과 같은 R 객체에 for loop
대신 반복적으로 동일한 함수를 적용할 때 활용된다. *apply()
계열 함수에 대해서는 데이터 프레임 에서 더 상세하게 배울 것임
split()
함수
tapply()
는 주어진 요인의 수준에 따라 특정 함수를 적용하지만,split()
은 데이터를 요인의 수준(그룹) 별로 데이터를 나누어 리스트 형태로 반환
split()
함수 사용 예시
$F
[1] 8300 5200 3000 4000 6300 2700
$M
[1] 5500 8500 3500 6800 4200 2900
$F.1
[1] 3000 4000 2700
$M.1
[1] 3500 4200 2900
$F.2
[1] 5200 6300
$M.2
[1] 5500 6800
$F.3
[1] 8300
$M.3
[1] 8500
# 요인의 각 수준에 대한 인덱스를 반환하고자 하는 경우
abalone <- read.csv("http://archive.ics.uci.edu/ml/machine-learning-databases/abalone/abalone.data",
header = FALSE) # 전복 데이터셋
# V1: 전복의 종류
# F=암컷; M=수컷, I=새끼
g <- abalone[, 1] # 전복종류만 추출
set.seed(20200410)
idx <- sample(1:length(g), size = 10)
g <- g[idx]
split(1:length(g), g)
$F
[1] 1 6 8
$I
[1] 2 3 5 7
$M
[1] 4 9 10
2.6.2 테이블(table)
- 범주형 변수의 빈도 또는 분할표(교차표)를 표현하기 위한 객체(클래스)
- 범주 별 통계량(평균, 표준편차, 중위수, …) 요약
tapply()
함수를 이용한 테이블 만들기
- 길이가 12인 임의의 벡터
u
를 수준의 개수가 각각 3, 2인 factor의 조합으로 부분벡터로 분리 후length()
적용 \(\rightarrow\)tapply()
함수 사용
u <- runif(12)
f1 <- factor(c(4, 4, 3, 5, 5, 4,
3, 3, 4, 5, 5, 3))
f2 <- factor(c("a", "a", "a", "a", "b", "a",
"b", "b", "a", "a", "b", "b"))
tapply(u, list(f1, f2), length)
a b
3 1 3
4 4 NA
5 2 2
u
의 값과 상관 없이 두 factor 형 변수f1
과f2
의 조합에 따른 개수 반환 \(\rightarrow\) 분할표(contingency table)- 위 예시에서
f1
이 “4” 이고f2
가 “b” 인 경우는 없기 때문에 0 값이 있어야 하나,tapply()
함수 적용 시 결측값NA
를 반환 table()
: 하나 이상의 factor의 수준 또는 수준의 조합으로 분할표 생성- Factor가 3개 이상인 경우 배열로 다차원 분할표 표현
f2
f1 a b
3 1 3
4 4 0
5 2 2
[1] "integer"
$dim
[1] 3 2
$dimnames
$dimnames$f1
[1] "3" "4" "5"
$dimnames$f2
[1] "a" "b"
$class
[1] "table"
'table' int [1:3, 1:2] 1 4 2 3 0 2
- attr(*, "dimnames")=List of 2
..$ f1: chr [1:3] "3" "4" "5"
..$ f2: chr [1:2] "a" "b"
f1
3 4 5
4 4 4
# factor가 3개인 경우
year = c("1","1","2","3","3","4")
gender = c("M","M","F","M","F","F")
grade = c("A","C","B","B","A","C")
table(gender, grade, year)
, , year = 1
grade
gender A B C
F 0 0 0
M 1 0 1
, , year = 2
grade
gender A B C
F 0 1 0
M 0 0 0
, , year = 3
grade
gender A B C
F 1 0 0
M 0 1 0
, , year = 4
grade
gender A B C
F 0 0 1
M 0 0 0