R언어 이전 포스트 참고
2021/01/20 - [IT/R] - R언어 공부 정리 [4]
2021/01/19 - [IT/R] - R 언어 공부 정리 [3]
2021/01/18 - [IT/R] - R 언어 공부정리 [2]
2021/01/15 - [IT/R] - 분석 , 통계시 유용한 R 언어 설치와 기본 공부 정리
데이터를 합치는 방법 에는 left_join() 과 bind_rows() 가 있습니다.
우선 left_join() 과 bind_rows()는 dplyr라는 라이브러리를 로드해주어야합니다.
library(dplyr)
left_join() : 데이터 열 합치기
bind_rows() : 데이터 행 합치기
열 컬럼을 합치기 위해서 데이터 프레임을 두개 생성해줍니다.
test1 <- data.frame(id=c(1,2,3,4,5),
midterm=c(60,80,70,90,85))
test2 <- data.frame(id=c(1,2,3,4,5),
final=c(70,83,65,95,80))
두 데이터 프레임은 반드시 통합적으로 기준이 되는 공통된 컬럼 변수가 있어야합니다.
위의 프레임에는 id가 공통 컬럼 변수입니다.
두 프레임을 합쳐보도록 하겠습니다.
total <- left_join(test1,test2, by="id")
total
# 실행 결과
# id midterm final
# 1 1 60 70
# 2 2 80 83
# 3 3 70 65
# 4 4 90 95
# 5 5 85 80
이번에는 기존 exam 데이터프레임에 선생님을 left_join으로 추가해보도록 하겟습니다.
name <- data.frame(class=c(1,2,3,4,5),
teacher=c('kim','lee','park','choi','jung'))
name이라는 프레임에 class와 선생님 데이터를 추가하고 exam과 name을 컬럼병합을 해봅시다.
exam_new <- left_join(exam,name,by='class')
exam_new
# 실행 결과
id class math english science teacher
1 1 1 50 98 50 kim
2 2 1 60 97 60 kim
3 3 1 45 86 78 kim
4 4 1 30 98 58 kim
5 5 2 25 80 65 lee
6 6 2 50 89 98 lee
7 7 2 80 90 45 lee
8 8 2 90 78 25 lee
9 9 3 20 98 15 park
10 10 3 50 98 45 park
11 11 3 65 65 65 park
12 12 3 45 85 32 park
13 13 4 46 98 65 choi
14 14 4 48 87 12 choi
15 15 4 75 56 78 choi
16 16 4 58 98 65 choi
17 17 5 65 68 98 jung
18 18 5 80 78 90 jung
19 19 5 89 68 87 jung
20 20 5 78 83 58 jung
이번에는 행을 합치는 bind_rows 입니다.
group_a <- data.frame(id=c(1,2,3,4,5),
test=c(60,80,70,90,85))
group_a
group_b <- data.frame(id=c(6,7,8,9,10),
test=c(70,83,65,95,80))
group_b
group_a 에는 id가 1부터5인 사람의 점수 group_b 에는 id가 6부터 10인 사람의 점수가 있습니다.
bind_rows() 함수는 컬럼이 동일하면 합칠수 있습니다.
group_all <- bind_rows(group_a,group_b)
group_all
# 실행결과
id test
1 1 60
2 2 80
3 3 70
4 4 90
5 5 85
6 6 70
7 7 83
8 8 65
9 9 95
10 10 80
문제로 mpg와 병합할 데이터를 만들어보겠습니다.
fuel <- data.frame(fl=c('c','d','e','p','r'),
price_fl=c(2.35,2.36,2.11,2.76,2.22),
stringsAsFactors = F)
이 f1을 기준으로 mpg에 가격컬럼을 추가해보겟습니다,
mpg_1 <- left_join(mpg,fuel,by="fl")
새로 생성한 mpg_1 에서 model, fl , price_fl만 추출해서 상위 6개를 확인해보겠습니다.
mpg_1 %>% select(model,fl,price_fl) %>% head()
예제 문제입니다.
midwest 데이터에서 popadults는 해당지역의 성인인구 , poptotal은 전체인구입니다.
midwest 데이터에서 전체인구 대비 미성년 인구 백분율을 변수 popchild로 추가하시오.
midwest_b <- midwest %>% mutate(popchild=(total-popadults)/total*100)
# 제대로 들어갔는지 확인하기 위해 select 해보겠습니다.
# midwest는 dim(midwest) 시 437행 31열 이라서 눈으로 직접 확인할수도 있지만
# 열 컬럼이 많은 빅데이터시에는 힘들수도 있습니다.
midwest_b %>% select(popchild)
# 실행결과
popchild
<dbl>
1 34.5
2 36.7
3 35.5
4 37.4
5 31.8
6 34.3
7 32.7
8 32.6
9 34.3
10 44.5
# ... with 427 more rows
이번엔 미성년 인구 비율이 가장 높은 상위 5개 지역(country)의 미성년 인구 백분율을 출력해봅시다.
midwest_b %>% arrange(desc(popchild)) %>% # 내림차순
select(county,popchild) %>% # country와 popchild 컬럼 확인
head(5) # 상위 5개
# 실행 결과
# A tibble: 5 x 2
county popchild
<chr> <dbl>
1 ISABELLA 51.5
2 MENOMINEE 50.6
3 ATHENS 49.3
4 MECOSTA 49.1
5 MONROE 47.4
분류하는 기준에 따라서 미성년 비율 등급변수를 추가하고, 각 등급에 몇개의 지역이 해당되는지 출력해봅시다.
기준은 40% 이상이면 large , 30~40% 사이면 middle , 30% 미만이면 small
midwest_c <- midwest_b %>% mutate(grade=ifelse(popchild>= 40,'large',ifelse(popchild>=30,'middle','small')))
# mutate 새로운 컬럼을 추가합니다. ifelse로 popchild가 40% 이상일시 large
# 이중조건문으로 popchild가 30% 이상일시 middle
# 그외에는 small 입니다
table로 출력시 수치로 바로 확인이 가능합니다.
table(midwest_c$grade)
# 실행 결과
large middle small
32 396 9
qplot 확인시 그래프로 확인할수 있습니다 .
qplot(midwest_c$grade)
popasian은 해당 지역의 아시아인 인구를 나타냅니다. 전체인구 대비 아시아인구 백분율 asianrate를 추가하고
하위 10개 지역의 state, country , asianrate을 출력해봅시다.
midwest_c %>% # midwest_c 데이터프레임에서
mutate(asian_rate=(asain/total)*100) %>% # 새로운 컬럼을 추가합니다 전체인구분의 아시아인구 백분율
arrange(asian_rate) %>% # 오름차순으로 정렬
select(state,county,asian_rate) %>% # state, country , asian_rate 컬럼만 선택
head(10) # 10개만 출력
데이터 정제하기 : 이상치 혹은 결측치가 있으면 데이터 분석이 어려울수 있음
결측치 : 데이터가 없는 경우 [ ex) NA ]
이상치 : 데이터가 이상한 데이터 [ 있을수가 없는 데이터 ex) 나이가 999살 , 100점만점인 시험에서 115점이다 ]
결측치가 있는 데이터 생성
df <- data.frame(sex=c('M','F',NA,'M','F'),
score=c(5,4,3,4,NA))
df
# 실행결과
sex score
1 M 5
2 F 4
3 <NA> 3
4 M 4
5 F NA
성별의 <NA>는 결측치 score의 NA는 결측치이다.
결측치를 감별하는 함수는 is.na 인데 정상이 False로 출력되고 비정상은 True로 출력됨
만약 정상이 True 비정상이 False로 하고싶으면 !is.na( ) 로 하면 된다.
is.na(df)
# 실행결과
sex score
[1,] FALSE FALSE
[2,] FALSE FALSE
[3,] TRUE FALSE
[4,] FALSE FALSE
[5,] FALSE TRUE
# 정상이 False # 비정상이 True
table(is.na(df)) # table() 빈도 테이블로 출력
# 실행결과
FALSE TRUE
8 2
# 성별에 결측치가 있는지 확인
table(is.na(df$sex))
#실행결과
FALSE TRUE
4 1
결측치가 있는 데이터는 연산이 불가능하다 .
sum(df$score)
[1] NA
결측치를 제거하는 방법은 filter를 사용하면 된다.
df %>% filter(!is.na(df$score)) # score에 있는 결측 데이터를 제거함
non_all <- df %>% filter(!is.na(df$score) & !is.na(df$sex))
# is.na 결측결과 score의 False sex에 False를 빼고 non_all에 넣는다
한번에 모든 결측치를 제거할려면 na.omit() 함수를 사용하면 된다.
df_omit <- na.omit(df) # 모든 결측치 제거
df_omit
# 실행결과
sex score
1 M 5
2 F 4
3 M 4
일반적인 함수사용시에는 na.rm = T 를 추가해서 사용이 가능하다.
mean(df$score, na.rm = T)
# [1] 4
sum(df$score,na.rm=T)
# [1] 16
csv_exam.csv 파일에서 수학점수 3행 8행 15행을 결측치로 NA를 삽입해보자
exam[c(3,8,15),'math'] <- NA
#결측치 확인을 위해 is.na 사용
table(is.na(exam$math))
exam의 결측치를 제거하고 수학점수의 총점 , 평균,중앙값을 구해봅시다.
exam %>% na.omit() %>% summarise(tot=sum(math),avg=mean(math),median=median(math))
# 실행결과
tot avg median
1 939 55.23529 50
na.omit() 방식 대신에 각각에 na.rm = T 를 넣는 방식으로 쓸수도 있다
exam %>% summarise(tot=sum(math,na.rm = T),avg=mean(math,na.rm=T),medi=median(math,na.rm = T))
결측치를 대처하는 방법으로 imputation이 있다
예를 들어 수학점수가 결측치가 있다면 0으로 대체하는 방법이다.
exam$math <- ifelse(is.na(exam$math),0,exam$math)
# is.na는 정상값이 False이므로 결측치가 있으면 0으로하고 아니면 그대로 둔다
mpg 데이터에 hwy 컬럼이 65,124,131,153,212 행에 NA를 할당하고 결측치가 있는지 확인해봅시다.
mpg_4 <- mpg
mpg_4[c(65,124,131,153,212),'hwy'] <- NA
table(is.na(mpg_4$hwy))
FALSE TRUE
229 5
filter()를 이용해서 hwy 변수의 결측치를 제거하고 어떤 구동방식의 hwy가 높은지 알아봅시다
단 하나의 dplyr 구문으로 작성하시오
mpg_4 %>% filter(!is.na(hwy)) %>% # 결측치를 제거한다
group_by(drv) %>%# 구동방식별
summarise(mean_hwy=mean(hwy)) # hwy 평균
# 실행결과
drv mean_hwy
<chr> <dbl>
1 4 19.2
2 f 28.2
3 r 21
이상치
이상치가 있는 데이터를 새로 생성해봅시다.
outlier <- data.frame(sex=c(1,2,1,3,2,1),
score=c(5,4,3,4,2,6))
# 성별은 1 ,2 로만 구성되어야 하고
# 점수는 1~5 사이에서 구성되어야 한다
즉 성별에서 3은 이상치이고 점수에서 6은 이상치 입니다.
빈도테이블을 이용해서 값을 확인해봅시다.
table(outlier$sex)
# 결과
1 2 3
3 2 1
성별의 1이 3개 2가 2개 3이 1개 입니다 여기서 3은 이상치!
마찬가지로 점수의 값을 확인해봅시다.
table(outlier$score)
2 3 4 5 6
1 1 2 1 1
6이 1개 발견되었습니다.
결측치의 경우 제외를 하거나 다른 연산이 가능한 값으로 변경처리했고
이상치의 경우는 NA로 처리하여 제외시키거나 아니면 다른 연산이 가능한 값으로 변경처리를 합니다.
outlier$sex <- ifelse(outlier$sex ==3,NA,outlier$sex)
outlier
# 결과
sex score
1 1 5
2 2 4
3 1 3
4 NA 4
5 2 2
6 1 6
outlier$score <- ifelse(outlier$score ==6,NA,outlier$score)
outlier
# 결과
sex score
1 1 5
2 2 4
3 1 3
4 NA 4
5 2 2
6 1 NA
성별 평균을 구해봅시다 .
outlier %>% filter(!is.na(sex) & !is.na(score) ) %>%
group_by(sex) %>% summarise(score_avg=mean(score))
# filter로 sex가 결측치가 아닌값 즉 !is.na True인값과 score가 정상인값을 추린후
sex별 점수의 평균을 구한다
sex score_avg
<dbl> <dbl>
1 1 4
2 2 3
만약 확실한 범위가 아닌경우 이상치 판단을 할때는 boxplot을 주로 이용하는데
boxplot은 표준편차로 +-3을 벗어나면 (이상치)극단치로 간주합니다.
mpg의 hwy의 이상치를 그림으로 확인해보면
boxplot(mpg$hwy) # 그림으로 확인
위와같이 확인할수 있고 통계치로 확인을 하려면
boxplot(mpg$hwy)$stats
#결과
[,1]
[1,] 12
[2,] 18
[3,] 24
[4,] 27
[5,] 37
attr(,"class")
1
"integer"
12보다 작거나 37 보다 큰경우에는 이상치,극단치로 간주한다.
고속도로 연비 극단치를 처리해 봅시다.
12보다 작거나 37보다 크면 NA 그외에는 그대로 사용합니다.
mpg$hwy <- ifelse(mpg$hwy < 12 | mpg$hwy > 37 , NA , mpg$hwy)
극단치가 몇개 있는지 NA를 확인해 봅시다 .
table(is.na(mpg$hwy))
FALSE TRUE
231 3
# 극단치가 3개인것을 확인할수 있음
drv별 고속도로 연비 평균을 산출해 봅시다.
mpg %>% group_by(drv) %>% summarise(drv_hwy_avg=mean(hwy,na.rm = T))
drv drv_hwy_avg
<chr> <dbl>
1 4 19.2
2 f 27.7
3 r 21
이번엔 임의의 이상치를 할당해서 테스트 해봅시다.
mpg[c(10,14,58,93),"drv"] <- "k"
mpg[c(29,43,129,203),"cty"] <- c(3,4,39,42)
10행 14행 58행 93행의 drv에 k의 값
29행 43행 129행 203행의 cty에는 3 4 39 42 가 들어갑니다
drv에 이상치가 있는지 확인해서 이상치를 결측치로 처리후 사라져는지 확인해봅시다 %in% 연산자를 활용!
table(mpg$drv) # drv의 이상치를 확인합니다
4 f k r
100 106 4 24
즉 k는 이상치 NA로 치환해줍니다
mpg$drv <- ifelse(mpg$drv %in% c('4','f','r'), mpg$drv,NA)
후에 다시 이상치를 확인합니다.
table(mpg$drv)
4 f r
100 106 24
이상치를 결측치로 변경했으므로 이상치는 없으나 NA 결측치가 4개가 존재합니다.
결측치를 확인하는 방법은
table(is.na(mpg$drv))
FALSE TRUE
230 4
즉 결측치 4개 존재
boxplot을 이용해서 이상치가 있는지 확인하고 상자그림의 통계치를 이용해
정상범위를 벗어난 값을 결측제거 처리한후 다시 상자그림을 이용해 이상치가 없는지 확인하시오.
boxplot(mpg$cty)$stats
[,1]
[1,] 9
[2,] 14
[3,] 17
[4,] 19
[5,] 26
# 9~26 이외는 NA로 처리
mpg$cty <- ifelse(mpg$cty < 9 | mpg$cty > 26 ,NA,mpg$cty)
9미만 26초과는 NA로 처리 그외에는 그대로
극단치가 사라진것을 확인할수 있음
하지만 이제 NA가 9개 존재함
table(is.na(mpg$cty))
FALSE TRUE
225 9
이상치를 제외한 다음 drv별로 cty 평균이 어떻게 다른지 알아보시오
mpg %>%
filter(!is.na(drv) & !is.na(cty)) %>% # 결측치 제외
group_by(drv) %>% # drv별로
summarise(mean_hwy = mean(cty)) # cty의 평균을 구한다.
# A tibble: 3 x 2
drv mean_hwy
<chr> <dbl>
1 4 14.2
2 f 19.5
3 r 14.0
'IT 기술 > R' 카테고리의 다른 글
R언어 공부정리 [7] (0) | 2021.01.25 |
---|---|
R언어 공부 정리 [6] (0) | 2021.01.22 |
R언어 공부 정리 [4] (2) | 2021.01.20 |
R 언어 공부 정리 [3] (1) | 2021.01.19 |
R 언어 공부정리 [2] (2) | 2021.01.18 |