R factor 함수 - R factor hamsu

이번 포스팅은 factor형 데이터 타입에 대해 자세히 알아보겠습니다.
R의 factor형은 범주화된 변수의 종류를 나타내기 위해 사용합니다.
범주형 자료란 변수를 특정 기준으로 배타적으로 나눌 수 있는 자료입니다.

예를 들면 다음과 같은 자료입니다.
성별(남/여), 학점(A/B/C/D/…), 지역(서울시/경기도/충청도/강원도/…)

R에서 범주형자료를 다룰 때는 문자형 자료와 잘 구별할 수 있어야 합니다.

미리 범주형인지 문자형인지 확인하고 적절하게 분석 목적에 맞게끔 변환시켜야 합니다.
이러한 과정들이 모두 데이터전처리의 일부입니다.

factor 함수 형태는 다음과 같습니다.

R factor 함수 - R factor hamsu

여기서 예제를 하나 보겠습니다.

데이터에는 카페 별 커피 가격이 나와있습니다.

R factor 함수 - R factor hamsu

이 때 오른쪽 테이블처럼 D업체의 아메리카노 가격을 추가하고 싶습니다.

먼저 데이터셋을 만듭니다.

data_test <- data.frame(name=c("A","B","C"),americano_cost = c(4800,4100,4300))

data_test 
  name americano_cost
1    A           4800
2    B           4100
3    C           4300

잘 만들어졌죠?
이제 D업체의 아메리카노가격을 데이터셋에 추가해봅시다.

하지만 그 전에 데이터셋의 구조를 확인합니다.
데이터셋의 구조는 str(데이터셋명) 이라는 함수를 써서 확인할 수 있습니다.
참고로 데이터셋 구조를 확인하는 것은 어떤 분석을 하든 상관없이 필수적으로 수행해야 합니다.

str(data_test)
'data.frame':   3 obs. of  2 variables:
 $ name          : Factor w/ 3 levels "A","B","C": 1 2 3
 $ americano_cost: num  4800 4100 4300

결과를 보니 프랜차이즈명에 factor 형으로 설정되어 있네요. 추가적으로 levels(수준) 가 A,B,C 로 설정되어 있습니다.
이 상태에서는 D업체를 추가하지 못합니다.

data_test2 <- rbind(data_test,c("D",2700))
Warning in `[<-.factor`(`*tmp*`, ri, value = "D"): invalid factor level, NA
generated

유효하지 않은 범주형 변수 수준(invalid factor level)을 가진다고 나오네요.

data_test2
  name americano_cost
1    A           4800
2    B           4100
3    C           4300
4 <NA>           2700

데이터를 보면 D가 아니라 NA(결측값)으로 입력이 되었네요. 먼저 levels(수준)을 A,B,C,D 로 설정해주어야 합니다.
다시 말해서, factor형 변수의 levels(수준)을 A,B,C에 D를 추가해야 합니다.

다음 코드를 통해 현재 설정되어 있는 범주형 변수의 수준을 확인합니다.

levels(데이터셋명$변수명) 를 쓰면 확인할 수 있습니다.

levels(data_test2$name)
[1] "A" "B" "C"

위 결과를 보니 D가 없네요.
그러면 여기에 D를 추가하겠습니다.

levels(data_test$name) <- c('A','B','C','D')
levels(data_test$name) 
[1] "A" "B" "C" "D"

c(‘A’,‘B’,‘C’,‘D’) 는 벡터의 요소가 A,B,C,D 이고 왼쪽에 있는 범주형 변수의 levels(수준)에 할당하였습니다.
여기까지 작업을 마쳤다면 정상적으로 값이 추가될 수 있습니다.

data_test3 <- rbind(data_test,c("D",2700))
data_test3
  name americano_cost
1    A           4800
2    B           4100
3    C           4300
4    D           2700

결과에서 D업체의 아메리카노 가격이 정상적으로 추가되었네요.

그러면~! 이제 반대로 카페 범주에서 A업체를 제거해보겠습니다.

data_test4 <- data_test3
data_test4$name<- factor(data_test3$name,levels = c('B','C','D'))
data_test4
  name americano_cost
1 <NA>           4800
2    B           4100
3    C           4300
4    D           2700

위 결과를 보면 A업체가 없어진 걸 볼 수 있습니다.

이해 안가는 부분이 있으면 댓글로 남겨주시고 공감 꾹 눌러주세요^^

R은 처음에 통계학의 도구로 쓰이기 시작했다. 통계학에서도 데이터 타입은 매우 중요하다. 통계학에서 카테고리형 변수를 표현하는 것이 '팩터(factor)'라는 데이터 구조이다. 이를테면 성별과 같은 것을 표현한다고 했을 때 성별에는 "M" 또는 "F"등과 같이 정해진 값들 가운데 하나가 선택된다. R에서는 이런 값들을 '팩터의 레벨(Levels) 이라고 부른다.

다음과 같은 문자형(character) 벡터로 시작해보자.

> gender <- c("M","F","F","M","F",NA)
> gender
[1] "M" "F" "F" "M" "F" NA 

이 벡터를 팩터로 바꾸려면 factor() 또는 as.factor() 함수를 사용한다.

> factor(gender)  //gender를 factor로 변환하여 출력함.
[1] M    F    F    M    F    <NA>
Levels: F M

> gender  //factor() 사용시 gender 값은 변하지 않음.
[1] "M" "F" "F" "M" "F" NA 


> gender <- as.factor(gender)  //factor 값을 gender에 적용함
> gender
[1] M    F    F    M    F    <NA>
Levels: F M

이런 팩터를 출력하게 되면 레벨 속성도 같이 출력된다. factor()함수는 주어진 벡터의 요소 값들을 같은 종류별로 묶은 다음 알파벳 순서로 레벨을 정하고, 그 레벨에 해당되는 값들을 다시 부여한다. 이런 팩터는 문자열이 아니기 때문에 출력된 모양을 보면 큰 따옴표가 없다는 것을 알 수 있다.

앞에서 ddf 라는 데이터 프레임을 만들 때 pt_name, categogo 백터가 팩터로 자동으로 바뀐 것은 data.frame () 이라는 함수의 stringAsFactors 라는 인자 때문이다. 이 것은 문자열 벡터를 자동으로 팩터로 변환하도록 기본 값이 설정되어 있다.

R factor 함수 - R factor hamsu
stringsAsFactors 기본값 설정.

이번에는 이 값을 FALSE로 줘보자. 보는 바와 같이 문자열이 그대로 유지되고 있음을 알 수 있다. 엑셀 등과 같이 사각형 모양의데이터가 들어 있는 파일을 R로  읽어올 때 read, csv(), read.table() 등과 같은 함수를 쓰게 된다. 이때 stringAsFactors 라는 옵션이 data.frame()함수의 기본 값과 같이 팩터로 전환되도록 되어 있는 경우가 많은데, 때에 따라서 필요한 방법을 선택하는 것이 좋다.

> id <- 1:10
> pt_name <- letters[1:10]
> categogo <- rep(c("Treat","Control"),5)
> scores <- sample(30:50,replace = TRUE,10)
> scores
 [1] 33 36 30 31 40 43 47 48 30 50
 
> df1 <- data.frame(id,pt_name,categogo,scores,stringsAsFactors = FALSE)

> str(df1) //pt_name과 categogo가 Factor 값으로 변환되지 않고 char 값을 유지한다.
'data.frame':   10 obs. of  4 variables:
 $ id      : int  1 2 3 4 5 6 7 8 9 10
 $ pt_name : chr  "a" "b" "c" "d" ...
 $ categogo: chr  "Treat" "Control" "Treat" "Control" ...
 $ scores  : int  33 36 30 31 40 43 47 48 30 50

■ 행렬과 배열

다음은 데이터 프레임과 같이 사각형 모양을 가진 행렬(matrix)에 대해서 알아보자. 행렬은 데이터 프레임과 같은 점도 있지만 다른 점이 많다. 행렬은 기본적으로 벡터를 가지고 만든다. 벡터에 디멘션(dim)속성이 부여된 것이기 때문에 데이터 프레임과 본질적으로 다르다. 벡터는 같은 데이터 타입을 가진 요소로 구성되고, 이것을 2차원적으로 배열한 행렬 역시 그 구성요소들은 모두 같은 데이터 타입을 가진다. 그러나 앞에서 본 데이터 프레임의 경우 그것을 구성하는 열들은 서로 다른 데이터 타입이 가능했다.

> j <- 1:35
> attr(j,"dim") <- c(5,7)
> j
     [,1] [,2] [,3] [,4] [,5] [,6] [,7]
[1,]    1    6   11   16   21   26   31
[2,]    2    7   12   17   22   27   32
[3,]    3    8   13   18   23   28   33
[4,]    4    9   14   19   24   29   34
[5,]    5   10   15   20   25   30   35
> class(j)
[1] "matrix"

행렬은 벡터를 matrix()함수로 넘겨서 만들 수도 있다. nrow는 행의 수, ncol에는 열의 수를 부여한다.

> matrix(k,nrow=5,ncol=7)
     [,1] [,2] [,3] [,4] [,5] [,6] [,7]
[1,]    1    6   11   16   21   26   31
[2,]    2    7   12   17   22   27   32
[3,]    3    8   13   18   23   28   33
[4,]    4    9   14   19   24   29   34
[5,]    5   10   15   20   25   30   35

벡터를 2차원으로 배열하여 행렬을 만들 때 열 방향으로 값들을 재배열한다. 만약 행을 기준으로 값을 재배열하고자 한다면 byrow = TRUE 라는 옵션을 사용한다.

> l<- 1:35
> matrix(l,nrow=5,ncol=7,byrow=TRUE)
     [,1] [,2] [,3] [,4] [,5] [,6] [,7]
[1,]    1    2    3    4    5    6    7
[2,]    8    9   10   11   12   13   14
[3,]   15   16   17   18   19   20   21
[4,]   22   23   24   25   26   27   28
[5,]   29   30   31   32   33   34   35

행렬의 합은 +, 곱은 %*% 연산자를 사용한다. t()는 행렬을 전치(transpose)한다. 수학적으로 행렬의 곱이 성사되려면 앞의 행렬의 열의 개수와 두의 행렬의 개수가 같아야 한다.

> a <- matrix(1:6,nrow=2)
> b <- matrix(3:8,nrow=2)
> a
     [,1] [,2] [,3]
[1,]    1    3    5
[2,]    2    4    6
> b
     [,1] [,2] [,3]
[1,]    3    5    7
[2,]    4    6    8
> a+b
     [,1] [,2] [,3]
[1,]    4    8   12
[2,]    6   10   14
> a%*%t(b)
     [,1] [,2]
[1,]   53   62
[2,]   68   80

R에는 행렬의 연산과 관련된 다양한 함수들이 준비되어 있다. 다음 rbind() 는 행으로 두 행렬을 합치고, cbind()는 열로 두 행렬을 합친다. 이런 행렬은 2차원적인 디멘션을 가지는 것으로, 배열(array)의 특수한 경우이다.

> rbind(a,b)
     [,1] [,2] [,3]
[1,]    1    3    5
[2,]    2    4    6
[3,]    3    5    7
[4,]    4    6    8
> cbind(a,b)
     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    1    3    5    3    5    7
[2,]    2    4    6    4    6    8

다음은 벡터 a를 2행,5열로 된 것을 5층으로 쌓아 올린 배열이다. 3차원 이상의 구조를 지닌 데이터는 쉽게 와닿지 않기 때문에 이런 배열은 자주 사용하지 않는다.

> a <- 1:50
> dim(a) <- c(2,5,5)
> a
, , 1

     [,1] [,2] [,3] [,4] [,5]
[1,]    1    3    5    7    9
[2,]    2    4    6    8   10

, , 2

     [,1] [,2] [,3] [,4] [,5]
[1,]   11   13   15   17   19
[2,]   12   14   16   18   20

, , 3

     [,1] [,2] [,3] [,4] [,5]
[1,]   21   23   25   27   29
[2,]   22   24   26   28   30

, , 4

     [,1] [,2] [,3] [,4] [,5]
[1,]   31   33   35   37   39
[2,]   32   34   36   38   40

, , 5

     [,1] [,2] [,3] [,4] [,5]
[1,]   41   43   45   47   49
[2,]   42   44   46   48   50