일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- livedata
- relay
- Gradle
- Hilt
- activity
- boj
- AWS
- android
- textfield
- 프로그래머스
- ProGuard
- 암호학
- 코드포스
- pandas
- 코루틴
- 백준
- Coroutine
- GitHub
- Codeforces
- TEST
- 쿠링
- androidStudio
- architecture
- Coroutines
- MiTweet
- Compose
- MyVoca
- Python
- Rxjava
- Kotlin
- Today
- Total
이동식 저장소
4. dplyr 본문
dplyr
의 함수를 이용하여 데이터 프레임을 다양한 방법으로 다듬을 수 있다. dplyr
함수는 세 가지 그룹으로 나눌 수 있다. filter()
, slice()
, arrange()
, distinct()
와 같이 행(row)을 대상으로 작업하는 함수, select()
, rename()
, mutate()
, relocate()
와 같이 열(column)을 대상으로 작업하는 함수, 요약 통계량을 계산하는 함수 summarise()
가 있다.
1. 행을 작업 대상으로 하는 함수
1.1 조건에 의한 행 선택: filter()
filter()
를 이용하여 특정한 조건을 만족하는 행을 선택할 수 있다. 조건을 설정할 때에는 다양한 비교 연산자(>, <, !=, == 등)와 논리 연산자(&, |, !)가 사용되며, %in%
도 유용하게 사용된다. &
대신 ,
를 쓸 수도 있다.
var %in% c(x, y, ...)
는 변수 var
이 c(x, y, ...)
의 값 중 하나를 가질 때 TRUE
를 반환한다. |
보다 %in%
을 쓰는 게 여러 면에서 더 좋다.
벡터 또는 스칼라 x
가 특정 구간에 속하는지를 확인하려면 x >= left, x <= right
로 쓸 수도 있지만, between(x, left, right)
로도 같은 결과를 얻을 수 있다.
결측값의 확인은 is.na()
로 할 수 있다.
1.2 인덱스에 의한 행 선택: slice()
slice()
slice()
를 사용하여 특정 행을 선택하거나 제거할 수 있다. 양의 정수를 입력하면 해당 행을 선택하고, 음의 정수를 입력하면 해당 행을 제거한다. 예를 들어 df
의 5-10번째 행을 선택하고자 한다면 df %>% slice(5:10)
을 실행해야 한다. 만약 5-10번째 행을 제거하고자 한다면 df %>% slice(-(5:10))
을 실행해야 한다. 괄호에 주의하자.
df
의 마지막 행을 선택하고자 할 때는 n()
을 함께 사용하면 좋다. n()
은 데이터 프레임의 행의 개수를 반환하는 함수이며, 단독으로 사용될 수는 없고 dplyr
의 함수와 함께 사용되어야 한다.
df %>% slice(n())
slice_head(), slice_tail()
데이터 프레임의 처음 또는 마지막 몇 행을 선택하고자 할 때 사용하는 함수이다. 행의 개수를 지정할 때는 n=10
처럼, 선택할 행의 비율을 지정할 때는 prop=0.1
처럼 사용하면 된다.
df %>% slice_head(n=10) # 앞에서부터 10개의 행을 선택
df %>% slice_tail(prop=0.3) # 뒤에서 비율 0.3만큼 행을 선택
랜덤으로 행 선택: slice_sample()
랜덤으로 행을 선택하고자 할 때 slice_sample()
을 사용할 수 있다. 마찬가지로 n
과 prop
을 사용하여 행의 개수 또는 비율을 지정할 수 있으며, 복원추출을 하고자 한다면 replace=TRUE
를 설정해야 한다. 기본적으로는 비복원추출을 실행한다.
df %>% slice_sample(n=3)
df %>% slice_sample(prop=0.2, replace=TRUE)
slice_max(), slice_min()
특정 변수가 가장 크거나 가장 작은 행을 선택하고자 할 때 사용하는 함수이다. 데이터프레임을 특정 변수로 정렬한 후 위에서부터 행을 선택한다고 보면 좋다.
df %>% slice_max(var, n=10) # var이 가장 큰 10개의 행 선택
df %>% slice_min(var, prop=0.1) # var이 작은 순서대로 전체 행의 10%를 선택
1.3 행의 정렬: arrange()
특정 변수를 기준으로 행을 재배열할 때 arrange()
를 사용한다. 매개변수로는 정렬의 기준이 되는 변수를 넣으면 되는데, 2개 이상을 넣을 경우 앞의 변수값이 같을 때 뒤의 변수가 기준으로 사용된다. 기본적으로 오름차순 정렬되며, 내림차순으로 정렬할 때는 desc()
를 같이 사용해야 한다.
df %>% arrange(var1) # var1으로 오름차순
df %>% arrange(var1, desc(var2)) # var1으로 오름차순, var1이 같을 경우 var2로 내림차순
1.4 중복된 행 제거: distinct()
중복된 행을 제거할 때 distinct()
를 사용한다. 매개변수로는 중복 여부를 결정할 변수를 넘겨준다. 매개변수가 없을 경우 모든 행이 같을 때에만 중복된 것으로 결정한다. .keep_all=TRUE
를 지정하면 데이터프레임의 모든 열을 가져올 수 있다.
df %>% distinct(var1, .keep_all=TRUE)
2. 열을 작업 대상으로 하는 함수
2.1 열 선택: select()
열 번호 또는 열 이름으로 선택
열 번호를 콤마 또는 구간으로 넘겨줄 수 있다.
df %>% select(1, 2, 3)
df %>% select(1:3)
열 이름은 열 번호와 동등하다.
df %>% select(var1:var3, var10)
논리 부정 !
또는 -
연산자를 이용하여 행을 제거할 수 있다. 정확히는 !
는 나열된 열의 여집합을, -
는 차집합을 구성한다. 상황에 따라 두 연산자를 사용한 결과가 미묘하게 달라질 수 있으므로 주의하자.
df %>% select(!c(1, 4, 10)) # 1, 4, 10번째 변수를 제외
df %>% select(-c(1, 4, 10)) # 같음
df %>% select(1:4, -1) # 1~4번 변수 중 1번 변수를 제외 = 1~3번 변수
df %>% select(1:4, !1) # 1~4번 변수 + (1번 변수 제외 나머지) = 전체
특정 타입의 변수만 선택
정수 또는 문자형 변수만 선택할 수 있다. where()
를 함께 사용한다.
df %>% select(where(is.numeric)) # 수(int, dbl)만 선택
df %>% select(where(is.numeric) | where(is.character)) # 수 또는 문자형 변수를 선택
select()에서 사용할 수 있는 함수
everything()
: 모든 변수를 선택한다.last_col()
: 마지막 변수를 선택한다.starts_with("x")
: 이름이x
로 시작하는 변수를 선택한다.ends_with("x")
: 이름이x
로 끝나는 변수를 선택한다.contains("x")
: 이름에x
가 들어가는 변수를 선택한다.num_range("x", 1:10)
:c("x1", "x2", ...)
와 같음
이 밖에도 all_of(vec)
, any_of(vec)
등의 함수가 존재한다. 이처럼 select()
에서 사용하는 열 선택 방법을 tidy-select
라고 하며, tidyverse
의 여러 함수에서 널리 사용된다.
변수를 벡터의 형태로 선택: pull()
데이터프레임 또는 tibble
에서 변수의 값은 $
기호를 이용하여 얻을 수 있다. 하지만 $
로 값을 얻는 경우 데이터프레임이 반환된다. 변수값을 벡터로 얻고자 한다면 pull()
을 사용해야 한다.
pull()
을 이용하여 변수를 선택하려면 변수의 위치 또는 이름을 var
로 지정하면 된다. 디폴트는 -1
로, 맨 마지막 변수가 선택된다.
df %>% pull(var=1) # 가져올 변수의 위치 지정
df %>% pull(var=var2) # 가져올 변수의 이름 지정
2.2 열 이름 변경: rename(), rename_with()
select()
로도 열 이름을 변경할 수 있으나, 이 경우 데이터프레임에서 이름이 변경된 변수만 반환되기 때문에 조금 불편할 수 있다. 새로운 이름을 부여하는 방식은 new_name=old_name
과 같다.(119p 참고)
df %>% select(model=model_name) # 변수 model_name이 model로 변경되고, model만 반환된다.
select()
에서 이름을 변경하지 않은 변수도 모두 가져오고 싶다면 everything()
을 사용해야 한다.
df %>% select(model=model_name, everything())
rename()
을 사용하면 이름이 변경되지 않은 변수도 기본적으로 모두 가져올 수 있다.
df %>% rename(model=model_name) # 이름을 바꾸고, df 전체가 반환됨
여러 변수의 이름을 공통된 형식으로 바꾸고자 할 경우 rename_with()
를 사용하면 좋다. rename()
으로도 할 수 있으나 이름을 일일이 입력해야 한다. 예컨대 모든 변수의 이름을 대문자로 바꾸려면 다음과 같이 하면 된다.
df %>% rename_with(toupper)
기본적으로는 모든 변수의 이름이 바뀐다. 변경 대상을 지정하고 싶다면 tidy-select
방식으로 조건을 주면 된다.
df %>% rename_with(toupper, contains("a")) # 이름에 a를 포함하는 변수만 대문자로 바뀜
2.3 열의 위치 변경: relocate()
열의 위치를 변경하고자 할 경우 relocate()
를 사용할 수 있다. tidy-select
방식으로 위치를 바꿀 열을 선택할 수 있다. 디폴트는 맨 앞으로 움직이며. .after
또는 .before
옵션을 주어 위치를 지정할 수 있다.
df %>% relocate(var5) # var5를 맨 앞으로
df %>% relocate(starts_with("a"), .after=var2) # 이름에 a가 포함되는 변수를 var2 뒤로 이동
2.4 열 추가: mutate(), transmute()
데이터프레임에 새로운 변수를 추가하고자 할 경우가 있다. 이때 데이터를 그냥 넣을 수도 있고, 데이터프레임에 있는 변수를 이용하여 새로운 변수를 추가할 수도 있다. 예를 들어 데이터프레임에 거리 dist
와 시간 time
이 있다면, 다음과 같이 속도 speed=dist/time
을 계산하여 추가할 수 있다.
df %>% mutate(speed=dist/time) %>% relocate(speed) # speed를 계산하고 맨 앞으로 옮김
mutate()
를 사용하면 데이터프레임에 변수가 추가되어 반환되고, transmute()
를 사용하면 추가한 변수만 얻을 수 있다.
if_else(condition, val1, val2)
를 사용하여 변수를 추가할 수도 있다. if_else()
는 조건 conditon
이 참인 경우 val1
을, 거짓인 경우 val2
를 반환한다. 또는 case_when()
을 사용할 수도 있다. case_when()
은 C에서의 switch
문과 비슷하다.
case_when(
condition1 ~ value_1,
condition2 ~ value_2,
...
TRUE ~ value_n)
조건은 위에서부터 아래로 평가되므로, 가장 좁은 범위의 조건이 맨 위에 위치해야 한다. 또한 모든 value_i
는 같은 타입이어야 한다. 맨 마지막의 TRUE
조건은 모든 조건에 해당하지 않는 경우에 발동한다.
df %>% mutate(speed_tag = case_when(speed < 5 ~ "SLOW",
speed < 10 ~ "MIDDLE",
TRUE ~ "FAST"))
3. 행 자료의 요약
변수의 요약통계량을 계산하고자 할 때 summarise()
를 사용할 수 있다. 첫 번째 매개변수는 데이터프레임이고, 그 뒤에 name=fun()
의 형식으로 fun()
의 실행 결과를 이름 name
으로 받을 수 있다.
df %>% sumamrise(total_num=n(), unique_num=n_distinct()) # 중복되지 않는 열의 개수
4. 데이터프레임 그룹화
함수 group_by()
를 이용하여 데이터프레임을 그룹화하고, 여기에 dplyr
함수를 적용해 보자.
4.1 그룹 데이터프레임 생성: group_by()
group_by()
는 한 개 이상의 변수를 사용하여 데이터프레임을 하나 이상의 그룹으로 나눈다.
df %>% group_by(var1) # var1이 같은 행끼리 그룹화
df %>% group_by(var1, var2) # var1, var2가 모두 같은 행끼리 그룹화
각 그룹에 속하는 행의 개수는 tally()
를 사용하여 알 수 있다.
df %>% group_by(var1) %>% tally() # var1로 구분된 각 그룹의 데이터의 수를 반환
그룹화된 데이터프레임에 구성 변수를 추가해서 그룹을 더 세분화할 수도 있다. 이 경우 .add=TRUE
를 지정해야 한다. .add=TRUE
를 지정하지 않은 경우 그룹 변수가 새로운 변수로 대체된다.
df %>% group_by(var1) %>% group_by(var2, .add=TRUE)
ungroup()
을 이용하여 그룹을 해체할 수 있다.
4.2 그룹 데이터 프레임에 dplyr
함수 적용하기
summarise()
그룹화된 데이터프레임에 summarise()
를 적용하면 그룹별로 요약통계량을 계산한다.
df %>% group(var1) %>% summarise(var2_mean=mean(var2))
예를 들어 다음의 코드를 실행하면 var1
그룹별로 var2
가 결측값인 행의 개수를 셀 수 있다.
df %>% group(var1) %>% summarise(na_count=sum(is.na(var2)))
벡터 x
에 대해 first(x)
와 last(x)
는 각각 x
의 첫 번째와 마지막 원소를 반환한다. 유사한 함수로 nth(x, i)
는 x[i]
를 반환한다. i
가 음수일 경우 x
의 뒤에서 i
번째 원소를 반환한다.
데이터에 결측값이 있을 경우, mean()
, max()
, min()
등을 사용할 때 na.rm=TRUE
를 반드시 지정하자.
select()
그룹을 구성하는 변수는 선택 대상이 아니어도 자동으로 선택된다.
arrange()
.by_group=TRUE
매개변수를 주면, 그룹 변수가 첫 번째 정렬 변수로 사용된다.
df %>% group_by(var1) %>% arrange(var2, .by_group=TRUE)
# var1로 정렬, var1이 같을 경우 var2 기준으로 정렬
mutate(), transmute()
그룹화된 데이터프레임에 mean()
, max()
등을 적용하면 각 그룹별로 결과를 계산한다. 따라서 그룹화된 데이터프레임에 이러한 함수를 사용하여 새로운 변수를 만들면 그룹화되지 않았을 때와 다른 결과가 나온다.
min_rank(x)
는 x
의 각 원소가 몇 번째로 작은지를 계산한다. 같은 값이 여러 개 존재할 경우 가장 작은 순위를 부여한다.
filter()
조건을 지정할 때 요약통계량 함수(mean()
, max()
등)를 사용하면 각 그룹별로 다른 값을 이용하여 행을 선택하게 된다.
slice()
그룹별로 행을 선택할 수 있다. 예를 들어 var1
의 그룹별로 var2
가 가장 큰 열을 선택하려면 다음과 같이 하면 된다.
df %>% group_by(var1) %>% slice_max(var2, n=1)
n(), cur_data (134p)
그룹별 행의 개수를 셀 때 n()
을 이용할 수 있다.
df %>% group_by(var1) %>% summarise(group_n=n()) # var1의 각 그룹별 데이터의 개수
5. 여러 열을 대상으로 작업 수행: across()
여러 열을 대상으로 같은 작업을 수행해야 하는 경우 across()
를 사용하면 편리하다.
across(.cols=everything(), .fns=NULL, ..., .names=NULL)
-
.cols
: 작업을 수행할 열.tidy-select
방식으로 열을 선택할 수 있다. -
.fns
: 수행할 함수. 다음의 세 가지 방법으로 지정할 수 있다.- 함수 이름: ex)
mean
purrr
방식으로 정의: ex)~ mean(.x, na.rm=TRUE)
..x
는 각 열을 의미한다.- 여러 함수의 리스트: ex)
list(Mean=mean, SD=sd)
- 함수 이름: ex)
-
...
:.fns
에 넘겨줄 추가 매개변수이다. 보통na.rm=TRUE
같은 걸 많이 쓴다. -
.names
: 결과물로 생성될 열의 이름을 지정할 수 있다. 선택된 열의 이름을{col}
, 함수의 이름을{fn}
으로 지정하여 문자열을 만들 수 있다. ex).names="{col}_{fn}"
summarise()와 함께 사용
모든 숫자형 변수의 평균값을 계산해 보자.
df %>% summarise(across(where(is.numeric), mean)))
숫자형 변수의 평균을, 범주형 변수의 level의 개수를 구해 보자.
df %>% summarise(across(where(is.numeric), mean),
across(where(is.factor), nlevels))
이름이 Num
으로 시작하는 변수의 평균과 표준편차를 구해 보자.
df %>% summarise(across(starts_with("Num"), list(M=mean, SD=sd)))
각 숫자형 변수의 결측값의 개수를 세어 보자.
df %>% summarise(across(where(is.numeric), ~ sum(is.na(.x))))
모든 숫자형 변수에 대해 중복되지 않는 값의 개수를 세어 보자.
df %>% summarise(across(where(is.numeric), ~ length(unique(.x))))
물론 특정 열만 지정할 수도 있다.
df %>% summarise(across(c(var1, var2), mean))
다른 함수와 함께 사용
숫자형 변수를 문자형으로 바꿔 보자.
df %>% mutate(across(where(is.numeric), ~ as.character(.x)))
var
로 시작하는 변수의 값이 모두 5
이상인 행을 선택해 보자.
df %>% filter(across(starts_with("var"), ~ .x >= 5))
적어도 하나의 결측값을 갖는 행을 모두 제거해 보자. 모든 행을 대상으로 하는 것이므로 .cols
는 생략할 수 있다.
df %>% filter(.fns = !is.na(.x))
그 밖에 다른 예시는 135~140p 참고
6. 행 단위 작업: rowwise()
dplyr
은 기본적으로 열 단위 연산에 특화되어 있다. 하지만 rowwise()
를 사용하여 행 단위 연산을 할 수 있다.
df1 = tibble(x=1:2, y=3:4, z=5:6)
# A tibble: 2 x 3
x y z
<int> <int> <int>
1 1 3 5
2 2 4 6
예를 들어 다음의 코드를 실행하면 각 행의 합이 계산된다.
df1 %>% rowwise() %>% mutate(total=sum(c(x, y, z)))
# A tibble: 2 x 4
# Rowwise:
x y z total
<int> <int> <int> <int>
1 1 3 5 9
2 2 4 6 12
rowwise()
없이 실행하면 모든 변수의 합이 계산된다.
df1 %>% mutate(total=sum(c(x, y, z)))
# A tibble: 2 x 4
x y z total
<int> <int> <int> <int>
1 1 3 5 21
2 2 4 6 21
자세한 사용 방법은 141~143p 참고
'CS > R 전산실습' 카테고리의 다른 글
7. R 프로그래밍 (0) | 2020.12.05 |
---|---|
5. ggplot2 (0) | 2020.12.03 |