데이터 변환 방법으로서

(1) 표준화

(2) 정규분포화

(3) 범주화

  - (3-1) 이산형화(discretization)    

  - (3-2) 이항변수화(binarization)

(4) 개수 축소

(5) 차원 축소

  - 주성분분석

  - 요인분석 

(6) 시그널 데이터 압축

 

중에서 이전 포스팅 (3-1) 이산형화(discretization)에 이어서 (3-2) 이항변수화(binarization)에 대해서 알아보겠습니다.  

 

이산형화가 다수의 구간으로 연속형 변수를 범주화 하는 것이라면, 이항변수화는 '1'과 '0'의 2개의 값으로 가변환(dummy variable)을 만드는 것을 말합니다.  연관분석이나 회귀분석 등에 이항변수화가 필요한 경우가 있습니다.  가령, 연관분석에서는 상품별 구매 여부(1, 0) 거래 데이터 (transaction data)를 가지고 패턴을 찾게 되는데요, 거주 지역이라든지 소득수준을 이항변수화 해서 행렬(matrix)로 만들어서 연관 규칙을 찾는데 활용할 수 있습니다 (더 정확히 말하자면, 메모리를 줄이기 위해서 sparse matrix 형식으로 저장).  또는 만약 시계열 자료가 고정계절변동(계절요인의 변동을 시간의 변화에도 일정하게 변동량을 유지하는 경우)을 가지는 경우에 가변수를 이용한 시계열 회귀모형을 시도해봄직 합니다. 

 

 

 R 데이터 변환 : (3-2) 이항변수화 (binarization)

 

[ 데이터 변환의 구조 ] 

 

 

(1) ifelse() 함수

 

ifelse() 함수를 활용해서 고객 프로파일 내 연령을 10대 간격으로 해서 20대 여부(1, 0), 30대 여부(1, 0), 40대 여부(1, 0), 50대 여부(1, 0) 의 가변수를 만들어보도록 하겠습니다.

 

> ## 고객 프로파일 데이터 프레임 생성

> cust_id <- c("c01", "c02", "c03", "c04", "c05", "c06", "c07")
> age <- c(25, 45, 31, 30, 49, 53, 27)
> 
> cust_profile <- data.frame(cust_id, age, stringsAsFactors = F)
> 
> cust_profile
  cust_id age
1     c01  25
2     c02  45
3     c03  31
4     c04  30
5     c05  49
6     c06  53
7     c07  27
> 
> sapply(cust_profile, class) 
    cust_id         age 
"character"   "numeric" 
> 
> ## 연령대 이항변수화
> cust_profile <- transform(cust_profile, 
+                           age_20 = ifelse(age >= 20 & age < 30, 1, 0), 
+                           age_30 = ifelse(age >= 30 & age < 40, 1, 0), 
+                           age_40 = ifelse(age >= 40 & age < 50, 1, 0), 
+                           age_50 = ifelse(age > 50 & age < 60, 1, 0))

 

> cust_profile
  cust_id age age_20 age_30 age_40 age_50
1     c01  25      1      0      0      0
2     c02  45      0      0      1      0
3     c03  31      0      1      0      0
4     c04  30      0      1      0      0
5     c05  49      0      0      1      0
6     c06  53      0      0      0      1
7     c07  27      1      0      0      0

 

 

 

위 화살표에서 보는 것처럼 해당 연령대에 '1'이, 아닌 곳에는 '0'이 들어가 있는 가변수들을 볼 수 있습니다.   이런 가변수를 활용해 연관분석을 하게 되면 if {연령대 = 20대, 케익구매} -> {반지 구매} 와 같이 구매 상품 정보뿐만 아니라 고객의 프로파일 정보도 같이 반영된, 그래서 타케팅 적중률을 더 높일 수 있는 연관규칙을 도출해낼 수 있습니다.

 

 

가변수를 이용한 시계열회귀모형을 예로 들자면, 아래의 식처럼 시점 t에서의 시계열 추세, 시점 t에서의 계절효과, 시점 t에서의 오차로 분해할 수 있습니다.  시계열회귀분석식을 자세히 보시면 [ D1,t = 1 시점 t에서 계절이 1인 경우, 0 그 이외의 경우 ] 라고 해서 가변수 처리 되어 있음을 알 수 있습니다.

 

 

 

> ## 시계열 데이터 생성 > Season <- c("S1", "S2", "S3", "S4", "S1", "S2", "S3", "S4") > SalesAmt <- c(300, 800, 400, 100, 280, 750, 390, 60) > TS <- data.frame(Season, SalesAmt, stringsAsFactors = F) > > TS Season SalesAmt 1 S1 300 2 S2 800 3 S3 400 4 S4 100 5 S1 280 6 S2 750 7 S3 390 8 S4 60 >

> ## 시계열회귀분석용 가변수 생성 > TS <- transform(TS, + Season1 = ifelse(Season=="S1", 1, 0), + Season2 = ifelse(Season=="S2", 1, 0), + Season3 = ifelse(Season=="S3", 1, 0)) > > TS Season SalesAmt Season1 Season2 Season3 1 S1 300 1 0 0 2 S2 800 0 1 0 3 S3 400 0 0 1 4 S4 100 0 0 0 5 S1 280 1 0 0 6 S2 750 0 1 0 7 S3 390 0 0 1 8 S4 60 0 0 0

 

 

 

 

예측모형적합을 위한 이항변수화를 할 때 한가지 주의해야 할 점이 있습니다.  바로 위의 캡쳐해놓은 표에 보면 S1(봄), S2(여름), S3(가을)은 가변수를 별도로 만들었지만, 노란색으로 동그라미 쳐놓은 S4 (겨울)은 별도의 가변수가 없고 그냥 S1 = 0, S2 = 0, S3 = 0 으로만 처리되어 있습니다.  이는 실수로 S4(겨울)을 빼먹은게 아니구요, 가변수 함정(dummy trap)을 피하기 위해 의도적으로 전체 계절의 갯수(여기서는 봄, 여름, 가을, 겨울의 4개)에서 1개를 빼게 됩니다.  운동회 때 서로의 간격을 맞추어서 줄을 서려면 제일 먼저 하는게 '기준'을 정하고 손을 번쩍 들어 크게 "기준~"하고 외칩니다.  그런 후에야 나머지 학생들이 "기준"이 되는 학생에 맞추어서 대열을 맞추게 되는데요, 계절효과를 반영하는 모형 적합에서도 "기준"이 되는 계절은 가변수를 안만들고, 나머지 계절만 가변수를 만들어서, "기준"이 되는 계절을 기준으로 상대적인 영향도를 계수로 모형에 반영하게 되는 원리입니다.  만약 계절의 전체 개수만큼 가변수를 만들게 되면 최소제곱추정법을 적용할 때 역행렬을 구할 수 없게 되는 가변수 함정에 빠지게 되어 해를 구할 수 없게 됩니다. 

 

시계열분석 통계이론이 잘 이해가 안되시더라도 일단 어떤 상황에서 이항변수화를 하게 되는지, R로는 ifelse() 함수를 써서 어떻게 변환하는지 정도만 이해하셨으면 일단 이번 포스팅에서는 얻어갈 것 다 얻어가신겁니다.

 

이번 포스팅이 도움이 되었다면 아래의 '공감 ~♡' 단추를 꾸욱 눌러주세요.^^

 

 

 

저작자 표시 비영리 변경 금지
신고
Posted by R Friend R_Friend

 

데이터 변환 방법으로서

(1) 표준화

(2) 정규분포화

(3) 범주화

  - (3-1) 이산형화(discretization)

  - (3-2) 이항변수화(binarization)

(4) 개수 축소

(5) 차원 축소

  - 주성분분석

  - 요인분석 

(6) 시그널 데이터 압축

 

중에서 우선 (3-1) 이산형화(discretization)에 대해서 알아보겠습니다. 

 

판별분석, 의사결정나무, 연관분석과 같은 분석 기법에서는 설명변수가 범주형 변수이어야지만 분석이 가능합니다.  분할표(contingency table)를 구하거나 카이제곱 검정을 할 때 범주형 변수를 대상으로 집단 간 독립성 검정을 하게 됩니다.  이처럼 분석기법에 따라서 연속형 변수를 범주형 변수로 변환을 한 이후에야 분석이 가능한 경우가 있습니다. 

 

혹은, 회귀분석을 한다고 했을 때 명목형, 범주형 자료에 대해서 가변수(dummy variable) 화 해서 분석을 진행해야 할 때도 있습니다.  가령 요일효과를 모형에 적합시키고자 한다면 요일 변수를 월요일 여부(mon_yn), 화요일 여부(tue_yn), ... , 토요일 여부(sat_yn) 등과 같이 1, 0 으로 코드화된 가변수로 변환해야 하는 경우도 있습니다.

 

이번 포스팅에서는 첫번째 경우의 (1) 이산형화, 두번째 경우의 (2) 이항변수화에 대해서 R에서는 어떻게 처리하는지 알아보도록 하겠습니다.

 

 

 R 데이터 변환 (3) 범주화 : 이산형화(discretization)

 

 

[ 데이터 변환 구성 ] 

 

 

 

 

(3-1) 이산형화 (Discretization)

 

연속형 변수를 범주형 변수로 변환하는 작업을 이산형화라고 합니다.  이산형화 변화 시에는 '몇 개의 범주로 나눌지?''구분선(cutting line)을 무슨 기준으로, 어디로 할지?'가 중요한 질문이 되겠습니다.

 

두 질문에 대한 학술적인 단 하나의 답안은 없습니다.  두 질문에 대해 공통적으로 분석/활용의 목적이 무엇이냐와 Biz. Domain Konwledge가 충분히 반영이 되어서 의사결정을 해야만 하고, 운영 과정상의 시행착오와 경험을 통한 긍정/부정적 피드백을 반영하여 지속적으로 개선해나가야 할 것입니다. 

 

이번 포스팅에서는 (a) 간격을 동일하게 한 범주화와 (b) quantile을 활용한 범주화 (c) frequency를 동일하게 한 범주화를 R로 어떻게 하는지Cars93 데이터셋의 고속도로 연비(MPG.highway)을 가지고 예를 들어보겠습니다.

 

(참고로, Cars93 은 MASS 패키지에 내장된 데이터 셋으로서, 자동차의 속성에 대해서 27개의 변수, 93개 자동차 관측치를 가진 데이터 프레임)

 

(a) 간격을 동일하게 한 범주화는 R의 hist() 함수로 히스토그램을 그려보는 것이 좋은 출발점이 될 수 있습니다. R의 hist() 함수의 디폴트 구간 개수가 꽤 좋은 결과를 내주거든요.  bin size를 조정해가면서 분포를 탐색해보고서 특정 구간에서 변곡점이 있다면, 혹은 특정 segment 나 factor 별로 분포상의 큰 차이를 보인다면 그 구분선을 가지고 범주를 나눌 수도 있을 것입니다.

 

R의 within() 함수를 활용하여 아래의 Cars93의 고속도로연비는 20~50까지 5단위씩 등간격으로 6개 범주로 나누어 보겠습니다. 

 

> library(MASS)
> str(Cars93)
'data.frame':	93 obs. of  27 variables:
 $ Manufacturer      : Factor w/ 32 levels "Acura","Audi",..: 1 1 2 2 3 4 4 4 4 5 ...
 $ Model             : Factor w/ 93 levels "100","190E","240",..: 49 56 9 1 6 24 54 74 73 35 ...
 $ Type              : Factor w/ 6 levels "Compact","Large",..: 4 3 1 3 3 3 2 2 3 2 ...
 $ Min.Price         : num  12.9 29.2 25.9 30.8 23.7 14.2 19.9 22.6 26.3 33 ...
 $ Price             : num  15.9 33.9 29.1 37.7 30 15.7 20.8 23.7 26.3 34.7 ...
 $ Max.Price         : num  18.8 38.7 32.3 44.6 36.2 17.3 21.7 24.9 26.3 36.3 ...
 $ MPG.city          : int  25 18 20 19 22 22 19 16 19 16 ...
 $ MPG.highway       : int  31 25 26 26 30 31 28 25 27 25 ...
 $ AirBags           : Factor w/ 3 levels "Driver & Passenger",..: 3 1 2 1 2 2 2 2 2 2 ...
 $ DriveTrain        : Factor w/ 3 levels "4WD","Front",..: 2 2 2 2 3 2 2 3 2 2 ...
 $ Cylinders         : Factor w/ 6 levels "3","4","5","6",..: 2 4 4 4 2 2 4 4 4 5 ...
 $ EngineSize        : num  1.8 3.2 2.8 2.8 3.5 2.2 3.8 5.7 3.8 4.9 ...
 $ Horsepower        : int  140 200 172 172 208 110 170 180 170 200 ...
 $ RPM               : int  6300 5500 5500 5500 5700 5200 4800 4000 4800 4100 ...
 $ Rev.per.mile      : int  2890 2335 2280 2535 2545 2565 1570 1320 1690 1510 ...
 $ Man.trans.avail   : Factor w/ 2 levels "No","Yes": 2 2 2 2 2 1 1 1 1 1 ...
 $ Fuel.tank.capacity: num  13.2 18 16.9 21.1 21.1 16.4 18 23 18.8 18 ...
 $ Passengers        : int  5 5 5 6 4 6 6 6 5 6 ...
 $ Length            : int  177 195 180 193 186 189 200 216 198 206 ...
 $ Wheelbase         : int  102 115 102 106 109 105 111 116 108 114 ...
 $ Width             : int  68 71 67 70 69 69 74 78 73 73 ...
 $ Turn.circle       : int  37 38 37 37 39 41 42 45 41 43 ...
 $ Rear.seat.room    : num  26.5 30 28 31 27 28 30.5 30.5 26.5 35 ...
 $ Luggage.room      : int  11 15 14 17 13 16 17 21 14 18 ...
 $ Weight            : int  2705 3560 3375 3405 3640 2880 3470 4105 3495 3620 ...
 $ Origin            : Factor w/ 2 levels "USA","non-USA": 2 2 2 2 2 1 1 1 1 1 ...
 $ Make              : Factor w/ 93 levels "Acura Integra",..: 1 2 4 3 5 6 7 9 8 10 ..
 

> ## 고속도로연비(MPG.highway) 히스토그램

> hist(Cars93$MPG.highway)
 

 

 

> ## Model, MPG.highway 두 개 변수만 선택해서 disc_1 데이터 프레임 생성

> disc_1 <- Cars93[,c("Model", "MPG.highway")]

> ## 상위 6개 미리보기

> head(disc_1) Model MPG.highway 1 Integra 31 2 Legend 25

3 90 26 4 100 26

5 535i 30 6 Century 31

>

>

> ## 6개 범주로 등간격 범주화

 

 

> disc_1 <- within( disc_1, { + MPG.highway_cd = character(0) + MPG.highway_cd[ MPG.highway >=20 & MPG.highway <25 ] = "20~25" + MPG.highway_cd[ MPG.highway >=25 & MPG.highway <30 ] = "25~30" + MPG.highway_cd[ MPG.highway >=30 & MPG.highway <35 ] = "30~35" + MPG.highway_cd[ MPG.highway >=35 & MPG.highway <40 ] = "35~40" + MPG.highway_cd[ MPG.highway >=40 & MPG.highway <45 ] = "40~45" + MPG.highway_cd[ MPG.highway >=45 & MPG.highway <=50 ] = "45~50" + MPG.highway_cd = factor(MPG.highway_cd, + level = c("20~25", "25~30", "30~35", + "35~40", "40~45", "45~50")) + })

> 

> ## 상위 6개 보기

> head(disc_1)
    Model MPG.highway MPG.highway_cd
1 Integra          31          30~35
2  Legend          25          25~30
3      90          26          25~30
4     100          26          25~30
5    535i          30          30~35
6 Century          31          30~35
 

 

 

> attributes(disc_1$MPG.highway_cd)
$levels
[1] "20~25" "25~30" "30~35" "35~40" "40~45" "45~50"

$class
[1] "factor"

 

 

> table(disc_1$MPG.highway_cd) # 분할표 생성

 

20~25 25~30 30~35 35~40 40~45 45~50 14 41 27 7 2 2

 

"MPG.highway" 변수 옆에 "MPG.highway_cd" 라는 범주형 변수가 생겼음을 알 수 있습니다.  나중에 통계분석과 연계하기 위해 "MPG.highway_cd" 변수를 within()함수의 제일 마지막 줄에서 요인(factor)으로 지정을 해줬고, level = c("20~25", "25~30", "30~35", "35~40", "40~45", "45~50")) 으로 순서형 요인(ordered factor)의 수준을 지정해주었습니다.

 

 

다음으로 (b) quantile을 활용한 범주화 방법에 대해서 알아보겠습니다.  MPG.highway를 0~25%, 25~50%, 50~75%, 75~100%의 구성비로 해서 4개 범주로 나누어보겠습니다.

 

> summary(disc_1$MPG.highway)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  20.00   26.00   28.00   29.09   31.00   50.00
> 

> # 4분위수의 1Q, 2Q, 3Q, 4Q를 기준으로 4개의 범주 생성

> disc_1 <- within( disc_1, {
+   MPG.highway_cd2 = character(0)
+   MPG.highway_cd2[ MPG.highway <  quantile(MPG.highway, 0.25) ] = "1Q"
+   MPG.highway_cd2[ MPG.highway >= quantile(MPG.highway, 0.25) 
+                    & MPG.highway < quantile(MPG.highway, 0.50) ] = "2Q"
+   MPG.highway_cd2[ MPG.highway >=quantile(MPG.highway, 0.50) 
+                    & MPG.highway < quantile(MPG.highway, 0.75) ] = "3Q"
+   MPG.highway_cd2[ MPG.highway >= quantile(MPG.highway, 0.75) ] = "4Q"
+   MPG.highway_cd2 = factor(MPG.highway_cd2, 
+                           level = c("1Q", "2Q", "3Q", "4Q"))
+ })
> 

> # 상위 6개 보기

> head(disc_1)
    Model MPG.highway MPG.highway_cd MPG.highway_cd2
1 Integra          31          30~35              4Q
2  Legend          25          25~30              1Q
3      90          26          25~30              2Q
4     100          26          25~30              2Q
5    535i          30          30~35              3Q
6 Century          31          30~35              4Q
 

 

 

> table(disc_1$MPG.highway_cd2)  # 분할표 생성

1Q 2Q 3Q 4Q 
22 17 25 29 

 

 

다음으로, (c) frequency를 동일하게 해서 4개 범주를 구성해보도록 하겠습니다.  먼저 고속도로연비(MPG.highway) 기준으로 정렬을 해줘야합니다.

 

> ## 고속도로연비(MPG.highway) 기준으로 오름차순 정렬

> disc_1 <- disc_1[order(disc_1$MPG.highway), ]

 

 

> dim(disc_1) # 93개 관측치, 4개 변수 [1] 93 4

 

## 관측치 개수

> dim(disc_1)[1]
[1] 93
> 

> disc_1$N <- seq(1:length(disc_1$MPG.highway)) # 1~93까지 순서대로 1씩 증가하는 N이라는 변수 생성

>

> # 동일 frequency (23개)로 4개 범주 생성

> disc_1 <- within( disc_1, { + MPG.highway_cd3 = character(0) + MPG.highway_cd3[ N <= 23 ] = "1st_Freq" + MPG.highway_cd3[ N >= 24 & N <= 46 ] = "2nd_Freq" + MPG.highway_cd3[ N >= 47 & N <= 69 ] = "3rd_Freq" + MPG.highway_cd3[ N >= 70 ] = "4th_Freq" + MPG.highway_cd3 = factor(MPG.highway_cd3, + level = c("1st_Freq", "2nd_Freq", "3rd_Freq", "4th_Freq")) + }) > > head(disc_1) Model MPG.highway MPG.highway_cd MPG.highway_cd2 N MPG.highway_cd3 17 Astro 20 20~25 1Q 1 1st_Freq 36 Aerostar 20 20~25 1Q 2 1st_Freq 26 Caravan 21 20~25 1Q 3 1st_Freq 89 Eurovan 21 20~25 1Q 4 1st_Freq 48 Q45 22 20~25 1Q 5 1st_Freq 87 Previa 22 20~25 1Q 6 1st_Freq

 

 

 

 

>

 

 

> table(disc_1$MPG.highway_cd3) 1st_Freq 2nd_Freq 3rd_Freq 4th_Freq 23 23 23 24

 

위의 분할표를 보면 4개 범주별로 23개, 23개, 23개, 24개(총 93개여서 마지막에 1개 더 넣음) 로 동일 frequency로 범주화가 되었음을 알 수 있습니다.  그런데 (c) 같은 frequency 로 범주화 시에 동일한 고속도로연비임에도 범주가 다르게 구분이 되는 수가 생깁니다.  아래 예에서 보면 고속도로연비가 28인 경우 "2nd_Freq"와 "3rd_Freq" 범주에 양다리 걸쳐있는것을 확인할 수 있습니다.  ("1st_Freq"와 "2nd_Freq"에도 고속도로연비 26이 양다리를 걸치고 있습니다.  또한 31이 "3rd_Freq"와 "4th_Freq"에 양다리를 걸치고 있습니다.)  이처럼 동일 frequency로 범주화시에는 중첩됨이 없이 범주화하기가 어려운 문제점이 있습니다.  따라서 해석의 용이성과 중첩 방지를 위해서 (a) 등간격 범주화 또는 (b) quantile 활용 범주화가 (c) 동일 freqency보다는 좀더 유용하다고 볼 수 있겠습니다. 

 

 

이항변수화 (binarization)은 다음번 포스팅에서 소개해드리겠습니다.

 

이번 포스팅이 도움이 되었다면 아래의 '공감 ~♡' 단추를 꾸욱 눌러주세요.^^

 

 

저작자 표시 비영리 변경 금지
신고
Posted by R Friend R_Friend

데이터는 크게 (1) 명목형 또는 순서형의 범주형 데이터 (categorical data)와 (2) 연속형 데이터 (continuous data) 로 구분할 수 있습니다.  R에서는 범주형 데이터를 요인(factor)형 데이터 구조라고 부르고 있으며, 순서(order)가 있는 경우는 순서형 요인(ordered factor)라고 해서 구분하기도 합니다.

 

분석하고자 하는 데이터 셋을 받으면 제일 먼저 데이터 구조와 데이터 형태를 탐색하게 됩니다.  그리고 분석 목적과 시나리오에 따라서 변수를 변환하게 되지요.  이번 포스팅에서는 연속형 변수를 범주형 변수로 변환하는 3가지 방법에 대해서 알아보도록 하겠습니다.  통계기법 중 도수분포표, 교차분할표, 카이제곱 검정이라든지, 로지스틱회귀분석, 그래프 중 막대그림, 원그림, 점그림 등의 경우 범주형 변수로 변환을 해야만 하며, 데이터 탐색 시에도 범주형 변수로 변환하여 분포 형태나 집단 간 비교를 하게 되므로 이번 포스팅은 활용도가 매우 높다고 하겠습니다.

 

cut() 함수, ifelse() 함수, within() 함수를 이용해서 아래 예를 들어 설명하도록 하겠습니다.

 

 

 연속형 변수를 범주형 변수로 변환하기: cut(), ifesle(), within()

 

(1) cut()

 

> ## 통계시험 점수 (stat_score) > student_id <- c("s01", "s02", "s03", "s04", "s05", "s06", "s07", "s08", "s09", "s10") > stat_score <- c(56, 94, 82, 70, 64, 82, 78, 80, 76, 78) > mean(stat_score) [1] 76 > hist(stat_score)

 

 

 

> # 데이터 프레임 생성
> score_d.f <- data.frame(student_id, stat_score)
> score_d.f
   student_id stat_score
1         s01         56
2         s02         94
3         s03         82
4         s04         70
5         s05         64
6         s06         82
7         s07         78
8         s08         80
9         s09         76
10        s10         78
 
> rm(student_id, stat_score)

 

 

위의 통계시험 성적을 가지고 cut() 함수를 이용하여 "수", "우", "미", "양", "가" 등급을 매겨보도록 하겠습니다.

right = TRUE 옵션을 주면 a < x <= b  와 같이 오른쪽 숫자까지 포함하여 해당 등급을 부여하게 됩니다.

right = FALSE 옵션을 주면 a<= x <b 의 조건으로 등급을 부여하며, include.lowest = TRUE 옵션을 주면 구성요소 값이 최소값과 같아도 변환을 시키게 됩니다.

 

> ## (1) cut()
> score_d.f <- transform(score_d.f, 
+                  stat_score_1 = cut(stat_score, breaks = c(0, 60, 70, 80, 90, 100), 
+                                     include.lowest = TRUE, 
+                                     right = FALSE, 
+                                     labels = c("가", "양", "미", "우", "수")
+                                     ), 
+                  stat_score_2 = cut(stat_score, breaks = c(0, 60, 70, 80, 90, 100), 
+                                     include.lowest = FALSE, 
+                                     right = FALSE, 
+                                     labels = c("가", "양", "미", "우", "수")
+                                     ),
+                  stat_score_3 = cut(stat_score, breaks = c(0, 60, 70, 80, 90, 100), 
+                                     include.lowest = FALSE, 
+                                     right = TRUE, 
+                                     labels = c("가", "양", "미", "우", "수")
+                                     ), 
+                  stat_score_4 = cut(stat_score, breaks = c(0, 60, 70, 80, 90, 100), 
+                                     include.lowest = TRUE, 
+                                     right = TRUE, 
+                                     labels = c("가", "양", "미", "우", "수")
+                                     )
+                        )
> 
> score_d.f
   student_id stat_score stat_score_1 stat_score_2 stat_score_3 stat_score_4
1         s01         56           가           가           가           가
2         s02         94           수           수           수           수
3         s03         82           우           우           우           우
4         s04         70           미           미           양           양
5         s05         64           양           양           양           양
6         s06         82           우           우           우           우
7         s07         78           미           미           미           미
8         s08         80           우           우           미           미
9         s09         76           미           미           미           미
10        s10         78           미           미           미           미

 

그런데 사용하다 보면 right 옵션, include.right 옵션, 그리고 labels 부여하는 순서도 그렇고, 머리속이 복잡해집니다. 아래의 ifelse()나 within() 함수는 위의 cut()보다는 수식의 부호를 직접 입력한다는 측면에서 사용하기에 더 편하고 직관적인 면이 있습니다.

 

 

(2) ifelse()

 

> attach(score_d.f)

> score_d.f <- transform(score_d.f, + stat_score_5 = ifelse(stat_score < 60, "가", + ifelse(stat_score >= 60 & stat_score < 70, "양", + ifelse(stat_score >= 70 & stat_score < 80, "미", + ifelse(stat_score >= 80 & stat_score < 90, "우", "수" + )))) + ) > detach(score_d.f) > score_d.f

 

 

 

 

 

> class(score_d.f$stat_score_5)
[1] "character"
 

 

위 표의 제일 오른쪽에 'stat_score_5' 변수가 ifelse() 함수를 이용해서 만든 범주형 변수가 되겠습니다.  cut() 대비 수식 등호, 부등호를 직접 입력하니 직관적으로 분석가가 원하는 범주로 수식을 적을 수 있는 장점이 있습니다만, 범주의 수준(level)이 많아질 수록 괄호 열고 닫는데 유의해야 합니다.  위의 예제의 경우 5개 범주로 나누는데 괄호 열고 "(((("  닫는 것이 "))))" 총 4개가 사용이 되었네요.  갯수 조심하지 않으면 콘솔 창에 에러날거예요.  RStudio 사용하면 ifelse() 괄호 하나씩 더해갈 때 마다 괄호 닫는것도 저절로 생기니 차근 차근 하시면 될겁니다.

 

그리고 stat_score_5 의 속성(class)이 요인(factor)이 아닌 문자(character)로 되어 있습니다.  만약 요인별로 통계 분석을 하고자 한다면 as.factor() 함수로 문자형을 요인형으로 먼저 변환을 시킨 후에 분석을 진행해야 합니다.

 

 

(3) within()

 

> ## within()
> score_d.f <- within( score_d.f, {
+   stat_score_6 = character(0) 
+   stat_score_6[ stat_score < 60 ] = "가" 
+   stat_score_6[ stat_score >=60 & stat_score < 70 ] = "양" 
+   stat_score_6[ stat_score >=70 & stat_score < 80 ] = "미" 
+   stat_score_6[ stat_score >=80 & stat_score < 90 ] = "우" 
+   stat_score_6[ stat_score >=90 ] = "수" 
+   
+   stat_score_6 = factor(stat_score_6, level = c("수", "우", "미", "양", "가"))
+ })
> 
> score_d.f$stat_score_6
 [1] 가 수 우 미 양 우 미 우 미 미
Levels: 수 우 미 양 가

 

 

 

within() 함수는 먼저 새로 만들 변수 stat_score_6 = character(0)  이라고 해서 문자형 변수라고 신규생성/지정을 해주고 시작합니다.

수식 등호, 부등호로 구간 설정하구요, 제일 마지막 줄에 factor() 함수로 해서 level = c("수", "우", "미", "양", "가") 라고 해서 수준을 지정해 줄 수 있습니다.  성적은 순서(order)가 있으므로 level 에 지정한 순서가 stat_score_6 요인 변수의 level 순서가 되겠습니다.

 

score_d.f$stat_score_6  라고 해서 indexing을 해서 보면 제일 아랫줄에 "Levels: 수 우 미 양 가" 라고 해서 순서가 제대로 인식되어 있음을 알 수 있습니다.  개인적으로 within() 함수를 순서형 요인변수 만들 때 위 셋 중에서 가장 많이 사용하는 편입니다.

 

아래는 제일 오른쪽에 within()함수로 만든 stat_score_6 변수까지 모두 한꺼번에 열어본 score_d.f 데이터 프레임이 되겠습니다. 

 

 

 

많은 도움이 되었기를 바랍니다.

 

이번 포스팅이 도움이 되었다면 아래의 '공감 ~♡' 단추를 꾸욱 눌러주세요.^^

 

저작자 표시 비영리 변경 금지
신고
Posted by R Friend R_Friend