R에서 변수, 정수, 요인(범주형) 변수를 안다는 것은 회귀분석이나, 머신러닝 실행 할때, 어떻게 구성 해야 하는지 아는 것과 같다. 실무에서는 예측셋(Predictive value :Categorical variable)인 경우가 많이 있으므로, 특히 이 부분을 잘 알고 넘어가면 앞으로 분석하는 데이터셋 만드는데, 도움이 많이 된다.
아래는 데이터 셋 링크 이다.
3장. R 언어의 기초
3-1 계산
3-1-5 변수의 정의
R에서 변수명을 선정 할 때 명심해야 하는 주의사항들이 있습니다.
- R에서 변수명은 대소문자를 구별한다. 따라서, y와 Y는 다릅니다.
- 변수명은 1x 또는 %와 같이 숫자나 기로호 시작하지 않습니다. .
- 변수명은 back.pay는 사용 가능하나 back pay 와 같이 공백을 포함하지 말아야 합니다.
- 변수명을 한글로 사용이 가능 하지만, 나중에 유사어의 함정에 빠지기 쉽습니다.
EX) 설비번호, 설비코드, 설비, 설비넘버 등..
가능 하면 변수는 간결하게 설정해, 오타로 인한 오류를 줄어야 하며, R에서 개체는 할당을 통해 값을 부등호와 마이너가가 합쳐진 화살표 모양의 <-
의 기호를 이용해 할당 합니다.
R에서 상수 x 에 5를 할당 하려면, x=5가 아니라 x<-5
입니다.
3-1.-6 연산자
+-*%/%%%^ | 산술연산 (더하기, 배기, 곱하기, 나누기, 몫, 나머지, 자승) |
>= < <= == != | 관계형 (큼, 이상, 작음, 이하, 같음, 같지 않음 |
! & | | 논리형 (not , and, or) |
~ | 모형 공식(함수로 모델링 됨) |
<- -> | 값 할당 |
$ | 리스트 색인(개체 요소명 연산자) |
: | 수열 만들기 |
몇 개의 연사자는 분석 모형 표현식에서 다른 의미를 값는 다. *는 곱하기보다 주 효 과와 교호효과 작용, :는 수열을 수열을 생성하는 것보다 두변수 사이의 교호작용을 의미하며, ^는 자승 보다는 표시된 자승까지 모든 교호작용을 의미한다.
예제 1
예제) 아래 표를 보고, 산술연산, 관계연산 값 할당, 리스트 색인을 하십시오.
NO | 이름 | 과일명 | 당도 |
1 | 철수 | 사과 | 8 |
2 | 영희 | 딸기 | 3 |
3 | 민우 | 사과 | 6 |
4 | 영수 | 배 | 8 |
5 | 서윤 | 딸기 | 3 |
6 | 서연 | 사과 | 4 |
7 | 하윤 | 배 | 9 |
8 | 지우 | 딸기 | 5 |
9 | 지유 | 포도 | 7 |
10 | 지아 | 바나나 | 5 |
11 | 수아 | 포도 | 10 |
12 | 하린 | 사과 | 8 |
# 패키지 로딩
library(dplyr)
##
## 다음의 패키지를 부착합니다: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
name <- c("철수","영희","민우","영수","서윤","서연","하윤","지우","지유","지아","수아","하린")
fruit <- c("사과","딸기","사과","배","딸기","사과","배","딸기","포도","바나나","포도","사과")
sugar <- c(8, 3, 6, 8, 3, 4, 9, 5, 7, 5, 10, 8)
#tibble에 할당
df <- tibble(name,fruit,sugar)
df
## # A tibble: 12 × 3
## name fruit sugar
## <chr> <chr> <dbl>
## 1 철수 사과 8
## 2 영희 딸기 3
## 3 민우 사과 6
## 4 영수 배 8
## 5 서윤 딸기 3
## 6 서연 사과 4
## 7 하윤 배 9
## 8 지우 딸기 5
## 9 지유 포도 7
## 10 지아 바나나 5
## 11 수아 포도 10
## 12 하린 사과 8
위에 있는 표를 이용해서 c() 함수를 이용해서 벡터를 만든 다음 tibble 함수를 이용해서 데이터 프레임을 만들었습니다.
이것을 이용해서 각종 연산자를 사용하겠습니다.
- 관계형 연산자를 사용하겠습니다. 아래에 있는 함수는
dplyr
패키지의filter()
함수를 사용 하였습니다.
여기에서의 R에서 연산자 같다 라는 의미를 =
를 사용하지 않과 ==
사용한다는 특징을 가지고 있습니다. . 코딩 하다 보면 매우 헤깔린 경우가 종종 발생 합니다.
# 사과만 찾아오기
filter(df, fruit == "사과")
## # A tibble: 4 × 3
## name fruit sugar
## <chr> <chr> <dbl>
## 1 철수 사과 8
## 2 민우 사과 6
## 3 서연 사과 4
## 4 하린 사과 8
관계형 연산자 중에서 이상, 낮은것 , 같지않음과 같은 연상을 아래와 같이 할수 있다.
# 당도높은 과일 찾기
filter(df, sugar > 6)
## # A tibble: 6 × 3
## name fruit sugar
## <chr> <chr> <dbl>
## 1 철수 사과 8
## 2 영수 배 8
## 3 하윤 배 9
## 4 지유 포도 7
## 5 수아 포도 10
## 6 하린 사과 8
filter(df, sugar >=7)
## # A tibble: 6 × 3
## name fruit sugar
## <chr> <chr> <dbl>
## 1 철수 사과 8
## 2 영수 배 8
## 3 하윤 배 9
## 4 지유 포도 7
## 5 수아 포도 10
## 6 하린 사과 8
#당도가 3이 아닌것 출력
filter(df, sugar != 3)
## # A tibble: 10 × 3
## name fruit sugar
## <chr> <chr> <dbl>
## 1 철수 사과 8
## 2 민우 사과 6
## 3 영수 배 8
## 4 서연 사과 4
## 5 하윤 배 9
## 6 지우 딸기 5
## 7 지유 포도 7
## 8 지아 바나나 5
## 9 수아 포도 10
## 10 하린 사과 8
- 논리형 연산자를 아래와 같이 계산 하겠습니다.
# 사과하고 포드를 찾기
filter(df, fruit == "사과" | fruit == "포도") # OR 연산자
## # A tibble: 6 × 3
## name fruit sugar
## <chr> <chr> <dbl>
## 1 철수 사과 8
## 2 민우 사과 6
## 3 서연 사과 4
## 4 지유 포도 7
## 5 수아 포도 10
## 6 하린 사과 8
filter(df, fruit == "사과" & fruit == "포도") # AND 연산자
## # A tibble: 0 × 3
## # … with 3 variables: name <chr>, fruit <chr>, sugar <dbl>
OR 형 연산자는 두가지 전부 나오지만, AND 연산자는 두가지의 조건이 맞아야 값이 나온다.
# 서윤이 딸기 산것 조회하기
filter(df, name == "서윤" & fruit == "딸기" ) # AND 연산자
## # A tibble: 1 × 3
## name fruit sugar
## <chr> <chr> <dbl>
## 1 서윤 딸기 3
아래와 같이 할당 연산자를 이용해서, 당도 값을 불러 올 수 있습니다.
# 값 할당
df$sugar
## [1] 8 3 6 8 3 4 9 5 7 5 10 8
R에서는 기본적으로 mean()
라는 함수를 이용해서 평균을 구하지만, 산술 연산을 이용해서 평균을 구할 수 있습니다.
# 평균 구하기
mean(df$sugar)
## [1] 6.333333
sum(df$sugar) / length(df$sugar)
## [1] 6.333333
3-1-7 정수
정수 형태로 입력 받기를 원하는 C 나 포트란 코드에 데이터를 전달하기 위해 정수 벡터를 사용한다. 작은 정수 데이터는 정확하고 간결하게 표현 할 수 있으며, 해당 정수의 범위는 -2,000,000,000(-2*10^9)
부터 +2,000,000,000(2*10^9)
까지 R 표현으로 -2e+09
부터 2e+09
까지 입니다. 주의 할 점은 integer함수를 사용해 벡트 클래스를 변경 하지 않도록 합니다. 예를 들면 아래와 같습니다.
# 벡터 X를 만들기
x<-c(5,3,7,8)
is.integer(x)
## [1] FALSE
is.numeric(x)
## [1] TRUE
integer 함수에 숫자 벡터를 인자로 설정해 실행 하면 정수로 변환 하려면 오류가 발생됩니다.
x<-intger(x)
integer(x)에서 다음과 같은 에러가 발생했습니다:인자 ’length’가 올바르지 않습니다.
따라서 숫자 벡터를 생성한 후 as.integer 함수를 사용해 다음과 같이 정수로 변환 합니다.
x<-c(5,3,7,8)
x<-as.integer(x)
is.integer(x)
## [1] TRUE
integer함수가 실수에 사용되면 trunc와 같은 기능을 실행 하고, 복소수에 사용되면 허수 부분을 제거 합니다.
as.integer(5.7)
## [1] 5
as.integer(-5.7)
## [1] -5
as.integer(5.7, -3i)
## [1] 5
3-1-8 요인
요인 facotrs은 고정 된 수의 수준을 갖고 있는 범주형 변수 입니다. . 간단한 요인 사례는 2개의 수준으로 구분되는 성별 변수다. 3명의 여자와 2명의 남자가 있다면, 다음과 같은 요인을 만들 수 있다.
gender <- factor(c("female", "male", "female", "male", "female"))
class(gender)
## [1] "factor"
mode(gender)
## [1] "numeric"
read.table 함수를 사용해 파일에서 데이터를 읽어 데이터 프레임을 생성 하는 경우가 많다. 이렇게 하면, 1개 이상의 문자열을 갖고 있는 요인들은 변환 시켜야 한다.
# 데이터 요인을 읽어 들인다.
data<-read.table("daphnia.txt", header = T)
attach(data)
head(data)
## Growth.rate Water Detergent Daphnia
## 1 2.919086 Tyne BrandA Clone1
## 2 2.492904 Tyne BrandA Clone1
## 3 3.021804 Tyne BrandA Clone1
## 4 2.350874 Tyne BrandA Clone2
## 5 3.148174 Tyne BrandA Clone2
## 6 4.423853 Tyne BrandA Clone2
# 범주화 작업을 하여야 한다.
data$Water <- as.factor(data$Water)
data$Detergent <- as.factor(data$Detergent)
data$Daphnia <- as.factor(data$Daphnia)
summary(data)
## Growth.rate Water Detergent Daphnia
## Min. :1.762 Tyne:36 BrandA:18 Clone1:24
## 1st Qu.:2.797 Wear:36 BrandB:18 Clone2:24
## Median :3.788 BrandC:18 Clone3:24
## Mean :3.852 BrandD:18
## 3rd Qu.:4.807
## Max. :6.918
위의 데이터 셋에서는 데이터를 아래와 같이 정의 합니다.
- Water : 물 (Tyne, Wear)
- Detergent : 세제
- Daphnia : 물벼룩
- Graowth.rate : 생장률
데이터 프레임은 연속형 반응 변수(Growth.rate)와 3개의 범주형 설명변수(Water, Detegent, Daphnia)를 가지고 있으며 모두 요인형 변수에 해당 된다. 통계 모델링에서 요인은 분산분석 (모든 설명 변수가 범주형)과 공분산 분석 (설명 변수의 몇 개는 범주형이고 몇 개는 연속형) 과 관련이 있습니다.
요인을 대상으로 하는 함수에는 is.factor가 있다. 이 함수는 변수가 요인인지 여부를 확인하고 싶을 때 사용하며 특히 요인 수준이 문자보다 숫자일 때 주로 사용합니다.
is.factor(data$Water)
## [1] TRUE
levels 함수는 요인 수준을 알아내기 위해 사용합니다.
levels(data$Detergent)
## [1] "BrandA" "BrandB" "BrandC" "BrandD"
nlevels 함수는 요인 수준의 수를 계산 합니다.
nlevels(data$Detergent)
## [1] 4
length함수를 요인 수준에 적용해도 동일한 수준의 수를 얻을 수 있습니다.
length(levels(data$Detergent))
## [1] 4
기본적으로 요인의 수준은 알파벳 또는 숫자 순으로 정리됩니다. 순서를 변경 하려면, 원하는 순서대로 입력한 요인 수준 벡터를 factor
함수릐 두번째 매개변수로 설정 합니다.
해당 요인의 수준을 지게차 톤수 (2.5TON,5.0TON,7.0TON,10.0TON,15.0TON) 대로 설정 하려면 숫자 순서로 되어 있는 것을(10.0TON,15.0TON,2.5TON,5.0TON,7.0TON) 변경 해야 합니다.
# 패키지 불러오기
library(dplyr)
library(readxl)
uptime <- read_excel("uptime.xlsx")
uptime$Ton <- as.factor(uptime$Ton)
#데이터 값을 factor화
attach(uptime)
# uptime 순서
summary(uptime$Ton)
## 10.0TON 15.0TON 2.5TON 5.0TON 7.0TON
## 76 42 30 30 53
다음 factor 함수를 사용해 요인 수준의 정렬 순서를 수정 합니다.
# 순서 정렬
Ton <- factor(Ton,levels = c("2.5TON",
"5.0TON",
"7.0TON",
"10.0TON",
"15.0TON"))
# 톤의 순서대로 정렬 됨
tapply(주유량, Ton , mean)
## 2.5TON 5.0TON 7.0TON 10.0TON 15.0TON
## 24.00000 83.00000 70.56604 81.18421 128.09524
요인에서는 ==와 !=와을 사용할 수 있다. 또한 요인은 동일한 수준을 갖고 있는 다른 요인과 비교할 수 있으며 이 경우 요인 수준은 반드시 동일한 순서일 필요는 없다. 예를 들어 요인 수준이 숫자값을 갖고 있다고 하더라도 이에 따른 정령적 연산 () 또는 (=)을 할 수 있다.
as.vector(unclass(as.factor(Daphnia)))
## [1] 1 1 1 2 2 2 3 3 3 1 1 1 2 2 2 3 3 3 1 1 1 2 2 2 3 3 3 1 1 1 2 2 2 3 3 3 1 1
## [39] 1 2 2 2 3 3 3 1 1 1 2 2 2 3 3 3 1 1 1 2 2 2 3 3 3 1 1 1 2 2 2 3 3 3
예제 2
Ex) factor범주형 변수는 연산을 할 수 있다고 하였다. 그럼 아래의 지게차 데이터셋 샘플을 가지고, 주유톤수, 정상여부 는 범주형으로 일자는 숫자로 바꾸어 가동시간 을 정상(YES), 비정상(NO)를 적으로 입력 할 수 있는지 클래스를 머신러닝인 randomForest을 이용하여, 예측 하십시오.
아래는 지게차 샘플 데이터 셋이다. 데이터는 주유일자 Ton, 주유량, 측정값, 가동시간, 정상 입력의 데이터가 있다.
# 패키지 로딩 randomForest
library(randomForest)
## randomForest 4.7-1
## Type rfNews() to see new features/changes/bug fixes.
##
## 다음의 패키지를 부착합니다: 'randomForest'
## The following object is masked from 'package:dplyr':
##
## combine
# 가동시간 데이터 셋 받기
library(readxl)
uptime <- read_excel("uptime.xlsx")
# 데이터 간단하게 보기
head(uptime)
## # A tibble: 6 × 6
## 주유일자 Ton 주유량 측정값 가동시간 정상입력
## <chr> <chr> <dbl> <dbl> <dbl> <chr>
## 1 2017-04-15 7.0TON 70 15593 -184 NO
## 2 2017-04-19 7.0TON 70 15608 15 YES
## 3 2017-04-24 7.0TON 80 15625 17 YES
## 4 2017-04-28 7.0TON 70 15640 15 YES
## 5 2017-05-03 7.0TON 70 15653 13 YES
## 6 2017-05-11 7.0TON 70 15666 13 YES
uptime 가동시간의 데이터 셋을 보면, 주유일자는 Date 날짜 타입이고, Ton은 charactor 타입으로 되어 있습니다.
# 데이터 요약해서 보기
summary(uptime)
## 주유일자 Ton 주유량 측정값
## Length:231 Length:231 Min. : 20.00 Min. : 0
## Class :character Class :character 1st Qu.: 70.00 1st Qu.:15036
## Mode :character Mode :character Median : 80.00 Median :16193
## Mean : 80.09 Mean :24066
## 3rd Qu.:100.00 3rd Qu.:39105
## Max. :160.00 Max. :75918
## 가동시간 정상입력
## Min. :-59984.00 Length:231
## 1st Qu.: 9.00 Class :character
## Median : 14.00 Mode :character
## Mean : 13.06
## 3rd Qu.: 19.50
## Max. : 60018.00
이것을 randomForest를 돌리려고 시도하면 아래와 같이 에러가 납니다.
# randomForest 머신러닝 시도
tryCatch(
randomForest(정상입력 ~ ., data = uptime),
error = function(e){
print(e)
})
## Warning in randomForest.default(m, y, ...): The response has five or fewer
## unique values. Are you sure you want to do regression?
## Warning in mean.default(y): 인자가 수치형 또는 논리형이 아니므로 NA를 반환합니다
## <simpleError in y - ymean: 이항연산자에 수치가 아닌 인수입니다>
데이터 유형을 바꾸고 다시 요약 하고 봅니다.
# 데이터 유형을 바꿈
uptime$주유일자<- unclass(as.Date(uptime$주유일자))
uptime$Ton <- as.factor(uptime$Ton)
uptime$정상입력 <- as.factor(uptime$정상입력)
# 데이터 요약해서 보기
summary(uptime)
## 주유일자 Ton 주유량 측정값
## Min. :17261 10.0TON:76 Min. : 20.00 Min. : 0
## 1st Qu.:17311 15.0TON:42 1st Qu.: 70.00 1st Qu.:15036
## Median :17351 2.5TON :30 Median : 80.00 Median :16193
## Mean :17362 5.0TON :30 Mean : 80.09 Mean :24066
## 3rd Qu.:17414 7.0TON :53 3rd Qu.:100.00 3rd Qu.:39105
## Max. :17478 Max. :160.00 Max. :75918
## 가동시간 정상입력
## Min. :-59984.00 NO : 55
## 1st Qu.: 9.00 YES:176
## Median : 14.00
## Mean : 13.06
## 3rd Qu.: 19.50
## Max. : 60018.00
주유일자는 숫자로 Ton은 범주형으로 바꾸었습니다.
이것을 다시 randomForest모델을 실행 시키면 아무런 문제 없이 실행 됩니다.
# randomForest 모델을 돌림
rf<-randomForest(정상입력 ~ ., data = uptime)
rf
##
## Call:
## randomForest(formula = 정상입력 ~ ., data = uptime)
## Type of random forest: classification
## Number of trees: 500
## No. of variables tried at each split: 2
##
## OOB estimate of error rate: 1.3%
## Confusion matrix:
## NO YES class.error
## NO 53 2 0.036363636
## YES 1 175 0.005681818
Tree 파리메터 갯수를 그래프로 나타냅니다. 아래 그래프를 보면 Tree 100에서 Error 값이 작아 졌습니다.
plot(rf)
randomForest Tree image |
어떤 변수의 영향이 많은지 아래 그래프와 같이 볼수 있습니다.
# 어떤 변수의 영향이 가장 많은가
varImpPlot(rf)
Randomforest 변수영향 |
역시 가동시간이 영향을 많이 받았습니다. 주유량하고, Ton은 예측변수(Predict Variable)로 사용하지 않아도 됩니다.
그 다음에, 데이터를 예측해 보겠습니다. 전혀 다른 데이터셋을 가지고 와서 예측 해보겠습니다.
# 예측데이터셋 가져오기
x <- read_excel("predict_uptime.xlsx")
# 데이터 유형 바꿈
x$주유일자<- unclass(as.Date(x$주유일자))
x$Ton <- factor(x$Ton,levels = c("2.5TON",
"5.0TON",
"7.0TON",
"10.0TON",
"15.0TON"))
# 예측하기
predict(rf, newdata = x )
## 1 2 3 4 5 6 7 8 9 10 11 12
## YES NO NO NO YES NO YES YES YES YES NO NO
## Levels: NO YES
# 결과를 보기
data.frame(x, 정상입력 =predict(rf, newdata = x ))
## 주유일자 Ton 주유량 측정값 가동시간 정상입력
## 1 17354 7.0TON 70 24207 33 YES
## 2 17359 7.0TON 90 42224 18017 NO
## 3 17362 7.0TON 90 24242 -17982 NO
## 4 17365 7.0TON 60 4257 -19985 NO
## 5 17367 7.0TON 70 4272 15 YES
## 6 17371 7.0TON 80 24289 20017 NO
## 7 17374 7.0TON 90 24310 21 YES
## 8 17392 7.0TON 90 24332 22 YES
## 9 17395 7.0TON 70 24348 16 YES
## 10 17399 7.0TON 80 24365 17 YES
## 11 17401 7.0TON 70 0 -24365 NO
## 12 17403 7.0TON 90 24398 24398 NO
예측값 x 는 7톤만 있으므로, Ton에 대한 factor 레벨값을 uptime 데이터셋과 맞추었습니다. 그런 다음에 predict()
함수를 사용해서 예측 하였습니다. 예측한 데이터는 위와 같이 정확하게 나왔습니다.
예제 3
데이터를 factor로 변환하고 나면, 범주의 순서서 알파벳 또는 숫자순으로 소팅이 된다. 이것을 원래대로 맞게 조정 하십시오. 데이터셋은 앞에서 사용한 uptime 데이터 셋 입니다.
library(readxl)
library(ggplot2)
##
## 다음의 패키지를 부착합니다: 'ggplot2'
## The following object is masked from 'package:randomForest':
##
## margin
uptime <- read_excel("uptime.xlsx")
uptime$Ton <- as.factor(uptime$Ton)
#데이터 값을 factor화
attach(uptime)
## The following object is masked _by_ .GlobalEnv:
##
## Ton
## The following objects are masked from uptime (pos = 5):
##
## 가동시간, 정상입력, 주유량, 주유일자, 측정값, Ton
# uptime 순서
summary(uptime$Ton)
## 10.0TON 15.0TON 2.5TON 5.0TON 7.0TON
## 76 42 30 30 53
# 톤별로 평균주유량 알기
tapply(주유량, Ton , mean)
## 2.5TON 5.0TON 7.0TON 10.0TON 15.0TON
## 24.00000 83.00000 70.56604 81.18421 128.09524
# 유류사용량 평균 그리기
uptime %>%
group_by(Ton) %>%
summarise(주유량_평균=mean(주유량))
## # A tibble: 5 × 2
## Ton 주유량_평균
## <fct> <dbl>
## 1 10.0TON 81.2
## 2 15.0TON 128.
## 3 2.5TON 24
## 4 5.0TON 83
## 5 7.0TON 70.6
uptime %>%
group_by(Ton) %>%
summarise(주유량_평균=mean(주유량)) %>%
ggplot(aes(x= Ton, y = 주유량_평균, fill = Ton)) +
geom_col() +
theme(text = element_text(size = 20))
범주형 level을 정하지 않은 그래프 |
위와 같이 그래프를 그렸을때, 숫자 순서별로 하였기 때문에, 그래프를 볼때 부자연스럽습니다.
하지만 아래와 factor를 level로 정리 하면, 그래프를 보는데, 아무런 문제가 없습니다.
# 순서 정렬
uptime$Ton <- factor(Ton,levels = c("2.5TON",
"5.0TON",
"7.0TON",
"10.0TON",
"15.0TON"))
# 톤의 순서대로 정렬 됨
tapply(주유량, Ton , mean)
## 2.5TON 5.0TON 7.0TON 10.0TON 15.0TON
## 24.00000 83.00000 70.56604 81.18421 128.09524
uptime %>%
group_by(Ton) %>%
summarise(주유량_평균=mean(주유량)) %>%
ggplot(aes(x= Ton, y = 주유량_평균, fill = Ton)) +
geom_col() +
theme(text = element_text(size = 20))
지게차 톤수대로 그래프를 그린 것을 볼 수 가 있습니다. 데이터의 머신러닝 분석을 하거나, 그래프를 그릴 때 매우 중요하다.
댓글 없음:
댓글 쓰기