서론
주어진 데이터를 그대로 사용하기보다 원하는 형태로 변형해 분석하는 경우가 많다. 그렇기에 데이터 파악 이후 자신이 원하는 대로 데이터를 가공하는 시간을 갖는다.
데이터 전처리
분석에 적합하게 데이터를 가공하는 작업을 '데이터 전처리(Data Preprocessing)'라고 한다. 일부를 추출하거나, 종류별로 나누거나, 여러 데이터를 합치는 등 데이터를 자유롭게 가공할 수 있어야 목적에 맞게 분석할 수 있다.
dplyr 함수 | 기능 |
filter() | 행 추출 |
select() | 열(변수) 추출 |
arrange() | 정렬 |
mutate() | 변수 추가 |
summaries() | 통계치 산출 |
group_by() | 집단별로 나누기 |
left_join() | 데이터 합치기(열) |
bind_rows() | 데이터 합치기(행) |
데이터 추출
데이터를 분석할 때 전체 데이터를 분석하기도 하지만 일부를 추출해 분석하기도 한다. "dplyr" 패키지의 "filter()"를 이용하면 데이터를 추출할 수 있다. 특히, 조건에 맞는 데이터를 추출하는 실습을 하기 위해 R에서 사용하는 '논리 연산자(Logical Operators)'와 '산술 연산자(Arithmetic Operators)'을 알아보자.
논리 연산자 | 기능 | 산술 연산자 | 기능 |
< | 작다 | + | 더하기 |
<= | 작거나 같다 | - | 빼기 |
> | 크다 | * | 곱하기 |
>= | 크거나 같다 | / | 나누기 |
== | 같다 | ^, ** | 제곱 |
!= | 같지 않다 | %/% | 나눗셈의 몫 |
| | 또는(or) | %% | 나눗셈의 나머지 |
& | 그리고(and) | ||
%in% | 매칭 확인 |
"dplyr" 패키지를 로드한 후 실습에 이용할 "csv_exam.csv" 파일을 데이터 프레임으로 만든다. "dplyr" 패키지의 "filter()"를 자신이 원하는 조건을 만족하는 행만 출력된다. "%>%"(pipe operator) 기호를 이용하여 함수들을 나열하는 방식으로 코드를 작성한다. 아래 예시는 반이 1 반인 학생들을 모두 출력했다. 해당 조건을 위 연산자를 이용해 자신이 원하는 조건의 변수를 추출하게 할 수 있다. ex) (class == 1 | class == 3), (class != 1 & math >= 50) 등
library(dplyr)
exam >- read.csv("csv_exam.csv")
exam %>% filter(class == 1)
## id class math english science
## 1 1 1 50 98 50
## 2 2 1 60 97 60
## 3 3 1 45 86 78
## 4 4 1 30 98 58
"%in%" 기호를 사용하면 코드를 좀 더 간결하게 작성할 수 있다. "%in%" 기호와 "c()"함수를 이용해 조건 목록을 입력하면 된다. "%in%" 기호는 변수의 값이 지정한 조건 목록에 해당하는지 확인하는 기능을 한다. 또한 새 변수를 만들 때처럼 "<-"기호를 이용하면 추출한 행으로 새로운 데이터를 만들 수 있다.
class_odd <- exam %>% filter(class %in% c(1,3,5))
## id class math english science
## 1 1 1 50 98 50
## 2 2 1 60 97 60
## 3 3 1 45 86 78
## 4 4 1 30 98 58
## 5 9 3 20 98 15
## 6 10 3 50 98 45
변수 추출
"select()"는 데이터에 들어 있는 수많은 변수 중 일부 변수만 추출해 활용하고자 할 때 사용한다. 괄호 안에 넣는 변수만 출력한다. 변수 앞에 "-"를 붙여 "-변수" 형태로 만들면 해당 변수를 제외한 모든 변수를 추출할 수도 있다.
exam %>% select(math, english)
## math english
## 1 50 98
## 2 60 97
## 3 45 86
## 4 30 98
...
dplyr 패키지의 함수들은 "%>%"를 이용해 조합할 수 있다는 장점이 있다. 함수를 조합하면 코드의 길이가 줄어 이해하기 쉬워진다.
R에서 `%>%` 기호는 "파이프" 연산자라고도 한다. 이 연산자는 데이터 처리 및 분석에서 코드를 더 읽기 쉽고 직관적으로 만들어 주는 도구이다.
`%>%` 연산자는 함수형 프로그래밍의 개념 중 하나인 "파이프라인"을 구현한 것이다. 이 연산자를 사용하면 데이터를 한 함수에서 다음 함수로 자연스럽게 전달할 수 있다. 이는 코드의 가독성을 높이고 중첩된 함수 호출을 피할 수 있다.
기존에는 이런 종류의 코드를 중첩된 함수 호출로 작성해야 했는데, `%>%` 연산자를 사용하면 체인 형태로 함수를 연결하여 코드를 더 읽기 쉽고 유지보수하기 쉽게 만들 수 있다.
exam %>% filter(class == 1) %>% select(english) # class가 1인 행만 추출한 다음 english 추출
exam %>% select(id, math) %>% head # id, math 추출 후 앞부분 6행까지 추출
정렬
"arrange()"를 이용하면 데이터를 원하는 순서로 정렬할 수 있다. arrange()에 정렬 기준으로 삼을 변수명을 입력하면 된다.그러면 해당 변수를 기준으로 오름차순으로 정렬이 된다. 만약 내림차순으로 정렬하고 싶다면 "desc()"에 적용하면 된다. 또한 정렬 기준으로 삼을 변수를 여러 개 지정하려면 쉼표를 이용해 변수명을 나열하면 된다.
exam %>% arrange(math) # math 오름차순 정렬
exam %>% arrange(desc(math)) # math 내림차순 정렬
exam %>% arrange(class, math) # class 및 math 오름차순 정렬(class로 정렬 후 math로 정렬)
파생 변수 추가
"mutate()"를 사용하면 기존 데이터에 파생 변수를 만들어 추가할 수 있다. "mutate()"에 새로 만들 변수명과 변수를 만들 때 사용할 공식 혹은 조건문 "ifelse()"을 입력하면 된다.
exam %>% mutate(total = math + english + science) # 총합 변수 추가
exam %>% mutate(total = math + english + science, mean = (math + english + science)/3) # 총합과 평균 변수 추가
exam %>% mutate(test = ifelse(science >= 60, "pass", "fail")) # 조건문을 이용해 합불 변수 추가
exam %>% mutate(total = math + english + science) %>% arrange(total) # 총합 변수 추가 후 정렬
집단별 요약
집단별 평균이나 집단별 빈도처럼 각 집단을 요약한 값을 구할 때는 "group_by()"와 "summarise()"를 사용한다. 이 함수들을 이용해 요약표를 만들면 집단 간에 어떤 차이가 있는지 쉽게 파악할 수 있다.
exam %>% summarise(mean_math = mean(math)) # math 평균 산출
exam %>% group_by(class) %>% summarise(mean_math = mean(math)) # 학급별로 분리 후 수학 평균 산출
exam %>% group_by(class) %>% summarise(mean_math = mean(math),
sum_math = sum(math),
median_math = median(math),
n = n(math)) # 학급별로 분리 후 수학 합계, 평균, 중앙값, 학생 수 산출
아래는 자주 사용하는 요약 통계량이다.
함수 | 의미 |
mean() | 평균 |
sd() | 표준편차 |
sum() | 합계 |
median() | 중앙값 |
min() | 최솟값 |
max() | 최댓값 |
n() | 빈도 |
데이터 합치기
하나의 데이터만 가지고 분석하기도 하지만 여러 데이터를 합쳐 하나의 데이터로 만든 후에 분석하기도 한다. 예를 들어, 중간고사 데이터와 기말고사 데이터를 합쳐 하나의 시험 점수 데이터를 만들어 분석할 수 있다.
데이터를 합치는 데에는 크게 두 가지 방법이 있다. 첫 번째는 데이터를 가로로 합치는 방법이다. 기존 데이터에 변수(열)를 추가한다고 볼 수 있다. 두 번째는 데이터를 세로로 합치는 방법이다. 기존 데이터에 행을 추가한다고 볼 수 있다.
가로로 합치기
"left_join()"을 이용하면 데이터를 가로로 합칠 수 있다.괄호 안에 합칠 데이터 프레임명을 나열하고, 기준으로 삼을 변수명을 by에 지정하면 된다. 또한, 이를 응용하면 특정 변수의 값을 기준으로 다른 데이터의 값을 추가할 수 있다.
name <- data.frame(class = c(1, 2, 3, 4, 5), teacher = c("kim", "lee", "park", "choi", "jung"))
exam <- left_join(exam, name, by = "class")
## 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
세로로 합치기
bind_rows()를 이용하면 데이터를 세로로 합칠 수 있다. 괄호 안에 합칠 데이터 프레임명을 나열하면 된다. 단, 세로로 데이터를 합칠 때는 두 데이터의 변수명이 같아야 한다.
group_a <- data.frame(id = c(1, 2, 3, 4, 5), test = c(60, 80, 70, 90, 85))
group_b <- data.frame(id = c(6, 7, 8, 9, 10), test = c(70, 83, 65, 95, 80))
group_all <- bind_rows(group_a, group_b) # 데이터 합치기
group_all
## id test
## 1 1 60
## 2 2 80
## 3 3 70
## 4 4 90
주섬주섬
- dplyr 패키지 함수들은 변수명 앞에 데이터 프레임명을 반복해 입력하지 않기 때문에 코드가 간결해진다는 장점이 있다.
- 정리한 접은 글이다.
## 1. 조건에 맞는 데이터만 추출하기
exam %>% filter(english>=80)
# 여러 조건 동시 충족
exam %>% filter(class == 1 & math >= 50)
# 여러 조건 중 하나 이상 충족
exam %>% filter(math >= 50 | english >= 90)
exam %>% filter(class %in% c(1, 3, 5))
## 2. 필요한 변수만 추출하기
exam %>% select(math)
exam %>% select(class, math, english)
## 함수 조합하기, 일부만 출력하기
exam %>% select(id, math) %>% head(10)
## 4. 순서대로 정렬하기
exam %>% arrange(math) # 오름차순 정렬
exam %>% arrange(decs(math)) # 내림차순 정렬
exam %>% arrange(class, math) # 여러 변수 기준 오름차순 정렬
## 5. 파생변수 추가하기
exam %>% mutate(total = math + english + science)
# 여러 파생변수 한 번에 추가하기
exam %>% mutate(total = math + english + science, mean = (math + english + science)/3)
# mutate()에 ifelse() 적용하기
exam %>% mutate(test = ifelse(scinence >= 60, "pass", "fail"))
# 추가한 변수를 dplyr 코드에 바로 활용하기
exam %>% mutate(total = math + english + science) %>% arrange(total)
## 6. 집단별로 요약하기
exam %>% mutate(total = math + english + science) %>% arrange(total)
# 각 집단별로 다시 집단 나누기
mpg %>% group_by(manufacturer, drv) %>% summarise(mean_cty = mean(cty))
## 7. 데이터 합치기
# 가로로 합치기
total <- left_join(test1, test2, by = "id")
# 세로로 합치기
group_all <- bind_rows(group_a, group_b)
- 예제 문제들이다.
mpg 데이터를 이용해 분석 문제를 풀어보자.
1. 자동차 배기량에 따라 고속도로 연비가 다른지 알아보자. 'displ'(배기량)이 4 이하인 자동차와 5 이상인 자동차 중 어떤 자동차의 hwy(고속도로 연비)가 평균적으로 더 높은 지 알아보자.
2. 자동차 제조 회사에 따라 도시 연비가 다른지 알아보자. 'adui'와 'toyita' 중 어느 'manufacturer'(자동차 제조 회사)의 'cty'(도시 연비)가 평균적으로 더 높은 지 알아보자.
3. 'chevrolet', 'ford', 'honda' 자동차의 고속도로 연비 평균을 알아보자. 이 회사들의 데이터를 추출한 후 'hwy' 전체 평균을 구해보자.
4. 'mpg' 데이터는 11개 변수로 구성되어 있다. 이 중 일부만 추출해 분석에 활용하려고 한다. 'mpg' 데이터에서 'class'(자동차 종류), 'cty'(도시 연비) 변수를 추출해 새로운 데이터를 만들자. 새로 만든 데이터 일부를 출력해 두 변수로만 구성되어 있는지 확인해 보자.
5. 자동차 종류에 따라 도시 연비가 다른지 알아보자. 앞에서 추출한 데이터를 이용해 'class'(자동차 종류)가 'suv'인 자동차와 'compact'인 자동차 중 어떤 자동차의 'cty'(도시 연비) 평균이 더 높은 지 알아보자.
6. 'audi'에서 생산한 자동차 중에 어떤 자동차 모델의 'hwy'(고속도로 연비)가 높은 지 알아보려고 한다. 'audi'에서 생산한 자동차 중 'hwy'가 1~5위에 해당하는 자동차의 데이터를 출력하자.
7. 'mpg()' 데이터 복사본을 만들고, 'cty'와 'hwy'를 더한 '합산 연비 변수'를 추가하자.
8. 앞에서 만든 '합산 연비 변수'를 2로 나눠 '평균 연비 변수'를 추가하자.
9. '평균 연비 변수'가 가장 높은 자동차 3종의 데이터를 출력하자.
10. 7~9번 문제를 해결할 수 있는 하나로 연결된 'dplyr'구문을 만들어 실행해 보자. 데이터는 복사본 대신 mpg 원본을 이용하자.
11. 'mpg'데이터의 'class'는 'suv', 'compact' 등 자동차를 특징에 따라 일곱 종류로 분류한 변수이다. 어떤 차종의 도시 연비가 높은지 비교해보려고 한다. 'class'별 'cty' 평균을 구해보자.
12. 앞 문제의 출력 결과는 'class' 값 알파벳 순으로 정렬되어 있다. 어떤 차종의 도시 연비가 높은지 쉽게 알아볼 수 있도록 'cty' 평균이 높은 순으로 정렬해 출력해 보자.
13. 어떤 회사 자동차의 'hwy'(고속도로 연비)가 가장 높은지 알아보려고 한다. 'hwy' 평균이 가장 높은 회사 세 곳을 출력해 보자.
14. 어떤 회사에서 'compact'(경차) 차종을 가장 많이 생산하는지 알아보려고 한다. 각 회사별 'compact' 차종 수를 내림차순으로 정렬해 출력해 보자.
- 대표적인 예이다.
미국 동북중부 437개 지역의 인구 통계 정보를 담고 있는 "midwest" 데이터를 사용해 데이터 분석 문제를 해결해 보자. "midwest"는 "ggplot2" 패키지에 들어 있다.
1. 'popadults'는 해당 지역의 성인 인구, 'poptotal'은 전체 인구를 나타낸다. "midwest" 데이터에 '전체 인구 대비 미성년 인구 백분율' 변수를 추가해 보자.
2. 미성년 인구 백분율이 가장 높은 상위 5개 'county'(지역)의 미성년 인구 백분율을 출력해 보자.
3. 분류표의 기준에 따라 미성년 비율 등급 변수를 추가하고, 각 등급에 몇 개의 지역이 있는지 알아보자.
4. 'popasian'은 해당 지역의 아시아인 인구를 나타낸다. '전체 인구 대비 아시아인 인구 백분율' 변수를 추가하고 하위 10개 지역의 'state'(주), 'county'(지역), 아시아인 인구 백분율을 출력하자.
참고
'프로그래밍 언어 > R' 카테고리의 다른 글
R 7. 그래프 만들기 (1) | 2024.01.31 |
---|---|
R 6. 데이터 정제하기 (0) | 2024.01.30 |
R 4. 데이터 파악하기 (2) | 2024.01.27 |
R 3. 데이터 프레임 (1) | 2024.01.26 |
R 2. 데이터 분석 이전 기본 개념 (2) | 2024.01.25 |
댓글