library(dplyr)
starwars |>
group_by(species, sex) |>
select(height, mass) |>
summarise(
height = mean(height, na.rm = TRUE),
mass = mean(mass, na.rm = TRUE)
)group_by() 란?
group_by()는 특정 집단의 범주별로 어떤 값들을 요약하거나 계산할 때 많이 활용되는 함수입니다.
by_species <- starwars |> group_by(species)
by_sex_gender <- starwars |> group_by(sex,gender)출력했을 때, 데이터가 그룹으로 묶인 것을 알 수 있습니다.
by_speciesby_sex_gendertally() 또는 count()를 이용해 그룹별 n수를 파악할 수도 있습니다.
sort 인자를 통해서 그룹 수가 많은 순서대로 정렬할 수 있습니다.
by_species |> tally()by_sex_gender |>
tally(sort=T)또한 group_by() 안에서 새로운 변수를 만들어 그 변수에 따른 계산을 할 수도 있습니다.
starwars |>
group_by(bmi_cat = cut(mass/(height/100)^2, breaks = c(0,18,23,25,30,Inf))) |>
tally()그룹 변수 정보 확인
그룹 변수를 지정해준 경우, group_keys() 를 통해 그룹 변수의 범주(종류)를 확인할 수 있습니다.
by_species |> group_keys()한편 group_vars() 는 group_by() 에 사용된 변수의 이름을 확인할 때 사용할 수 있습니다.
by_sex_gender |> group_vars()[1] "sex" "gender"
그룹 변수 변경 및 추가
기존의 그룹처리 되어있는 데이터에 group_by() 를 진행할 시, 새로운 그룹 변수로 덮어씌워집니다.
by_species는 앞서 group_by(species)를 통해 species별로 묶은 데이터죠. 여기서 group_by(homeworld)를 추가한다면 기존의 species에서 homeworld를 기준으로 그룹이 묶이게 됩니다.
by_species |>
group_by(homeworld) |>
tally()만약 기존의 그룹을 대체하는 것이 아니라 추가를 할 수도 있을텐데요. group_by()에 .add=T 인자를 추가할 경우, 기존에 있던 그룹 변수에 새로운 그룹 변수를 추가할 수도 있습니다.
by_species |>
group_by(homeworld, .add=T) |>
tally()그룹 변수 제거
그룹 처리된 데이터를 제거하고 싶은 경우, ungroup() 을 사용합니다.
by_species |>
ungroup() |>
tally()물론 특정 그룹 변수만 제외할 수도 있습니다. by_sex_gender에서 sex와 gender로 묶여있던 것을 ungroup()을 통해 sex만 제거하여 gender만 그룹으로 남아있게 되었습니다.
by_sex_gender |>
ungroup(sex) |>
tally()group_by()와 함께 쓰는 동사
다음으로 dplyr에서 group_by()와 자주 쓰이는 함수들을 알아보겠습니다.
1. summarise(), summarize()
summarise()와 group_by()가 함께 사용될 경우, 그룹별로 요약 계산을 수행합니다. 평균, 표준편차, 중앙값, 최소, 최대값과 같은 값을 출력할 수 있습니다.
by_species |>
summarise(
n=n(),
mean_height = mean(height,na.rm=T)
).groups인자는 출력되는 결과의 그룹 구조를 다루는 인자입니다. keep은 그룹으로 묶인 상태를 유지하는 반면, drop은 그룹으로 묶인 상태를 해제합니다.
by_sex_gender |>
summarise(n=n(), .groups = 'keep')by_sex_gender |>
summarise(n=n(), .groups = 'drop')2. select(), rename(), relocate()
rename()과 relocate()는 group_by()와 관계없이 동일한 작업을 수행합니다. 각각 열의 이름과 위치에만 영향을 미치게 때문입니다.
select()가 group_by()와 함께 쓰이면 그룹 변수가 항상 함께 선택됩니다.
by_species |> select(mass)그룹 변수가 함께 선택되는 것을 원치 않는다면 ungroup()을 먼저 사용해야 합니다.
by_species |> ungroup() |> select(mass)3. arrange()
arrange()가 group_by()와 함께 쓰일 경우, 그냥 사용하게 되면 group_by() 가 없을 때와 동일합니다. 그러나 .by_group=T 인자를 통해 그룹 변수를 기준으로 정렬되어 결과가 출력됩니다.
by_species |>
arrange(desc(mass)) |>
relocate(species, mass)by_species |>
arrange(desc(mass), .by_group = T) |>
relocate(species, mass)4. mutate(), transmute()
group_by()와 함께 새로운 변수를 생성할 경우, 그룹 별로 동일한 값이 들어가게 됩니다.
starwars |>
group_by(species) |>
mutate(mean_height = mean(height, na.rm=T)) |>
arrange(desc(species)) |>
select(species, height, mean_height)5. filter()
filter()와 group_by()를 함께 사용하여, 특정 그룹의 수를 기준으로 선택할 때 사용할 수 있습니다.
아래의 예시에서는 그룹 별 수가 1인 경우를 모두 제외하고 선택한 결과입니다.
by_species |>
filter(n()!=1) |>
tally()6. slice()
slice()와 slice() 계열 함수들이 group_by() 와 함께 사용될 경우, 그룹별로 해당되는 값이 출력됩니다.
# 그룹별 첫번째 값
by_species |>
slice(1) by_species |>
filter(!is.na(height)) |>
slice_min(height,n=2)Update: dplyr 1.1.0
dplyr 1.1.0 업데이트 이후에는 group_by()를 사용하지 않아도 다른 함수들에서 그룹 별 계산을 수행할 수 있습니다. 바로 .by 인자를 통해서 말이죠.
starwars |>
mutate(bmi = mass/(height/100)^2) |>
summarise(mean_bmi = mean(bmi, na.rm=T),.by=species)