숫자 벡터 다루기: 숫자 만들기부터 요약까지

숫자 벡터 다루기: 숫자 만들기부터 요약까지

데이터 과학의 근간은 숫자 벡터예요. 책 앞부분에서 이미 몇 번 써봤겠지만, 이 페이지에서는 숫자 벡터로 할 수 있는 일을 체계적으로 정리해 볼게요. 문자열로 묶인 숫자를 숫자로 바꾸는 법, 세기(count), mutate()와 잘 어울리는 변형 함수, 그리고 summarize()와 함께 쓰는 요약 함수 순서로 살펴볼게요.

출처: R for Data Science(2e) — Numbers

본문

숫자 만들기

R에는 정수(integer)와 실수(double) 두 종류의 숫자형이 있어요. 대부분의 경우 숫자는 이미 이 형태로 들어오지만, 가끔 문자열로 만나게 돼요. 예를 들어 열 머리글을 피벗하면서 숫자를 만들거나, 데이터 가져오기 과정에서 문제가 생긴 경우죠.

readr 패키지의 parse_double()은 문자열로 쓰인 숫자를, parse_number()는 숫자가 아닌 텍스트가 섞인 문자열에서 숫자만 뽑아내요. 통화나 퍼센트 데이터에 특히 유용해요.

x <- c("$1,234", "USD 3,513", "59%")
parse_number(x)
#> [1] 1234 3513 59

세기: count()

세기와 기본 산술만으로도 할 수 있는 데이터 과학이 생각보다 많아요. dplyr의 count()는 탐색과 검증 중에 빠르게 쓰기 좋아요.

flights |> count(dest)

가장 흔한 값을 보려면 sort = TRUE를 붙여요.

flights |> count(dest, sort = TRUE)

count()와 같은 계산을 group_by(), summarize(), n()으로 직접 할 수도 있어요. 그러면 동시에 다른 요약값도 구할 수 있죠.

flights |>
  group_by(dest) |>
  summarize(n = n(), delay = mean(arr_delay, na.rm = TRUE))

n()은 인자를 받지 않고 "현재 그룹"의 정보를 꺼내는 특별한 요약 함수라 dplyr 동사 안에서만 동작해요. 몇 가지 유용한 변형도 있어요.

  • n_distinct(x): 하나 이상의 변수에서 서로 다른 값의 개수를 세요.
  • count(x, wt = w): wt로 가중 개수를 계산해요. 예를 들어 각 비행기의 총 비행 거리를 셀 수 있어요.
  • 결측값 세기: sum(is.na(col))로 특정 변수의 결측값 개수를 셀 수 있어요.

숫자 변형

변형 함수는 출력 길이가 입력과 같아 mutate()와 잘 어울려요. 대부분은 base R에 이미 내장되어 있어요.

재활용 규칙(recycling rules): 왼쪽과 오른쪽의 길이가 다를 때 R은 짧은 벡터를 반복(재활용)해요. 예를 들어 air_time / 60처럼 벡터를 스칼라로 나누는 연산이 가능한 이유예요.

x <- c(1, 2, 10, 20)
x / 5
#> [1] 0.2 0.4 2.0 4.0
# 는 x / c(5, 5, 5, 5) 의 줄임 표현

보통은 길이 1짜리 수만 재활용하는 게 좋아요. 더 긴 벡터가 짧은 벡터의 배수가 아니면 경고가 나오지만, 배수면 경고 없이 조용히 동작해서 놓치기 쉬워요. 예를 들어 month == c(1, 2)처럼 쓰면 홀수 행은 1월, 짝수 행은 2월로 비교하는 바람에 원하지 않는 결과가 나와요. 그래서 tidyverse 함수들은 보통 길이 1 값만 재활용하는 더 엄격한 규칙을 써요.

pmin()pmax(): 여러 변수를 받아 각 행에서 최솟값·최댓값을 돌려줘요. 여러 관측을 받아 단일 값을 내는 요약 함수 min()·max()와는 다르다는 점을 주의해요.

모듈러 산술: %/%는 정수 나눗셈, %%는 나머지를 구해요. 예를 들어 출발 예정 시각(sched_dep_time)을 시(hour)와 분(minute)으로 분해할 때 유용해요.

flights |>
  mutate(
    hour = sched_dep_time %/% 100,
    minute = sched_dep_time %% 100,
    .keep = "used"
  )

요약 함수

요약 함수는 summarize()와 잘 어울리는데, 재활용 규칙 덕분에 mutate()와도 유용하게 쓸 수 있어요. 대표적인 예시를 정리하면 이렇습니다.

# 전체에서 차지하는 비율
x / sum(x)

# Z-점수 (평균 0, 표준편차 1로 표준화)
(x - mean(x)) / sd(x)

# 0~1 범위로 표준화
(x - min(x)) / (max(x) - min(x))

# 첫 관측값을 기준으로 한 지수
x / first(x)

요약 시 평균(mean())뿐 아니라 중앙값(median())이 더 적합한 경우도 있으니, 데이터 분포에 맞춰 골라 쓰는 게 좋아요.

더 알아보기

  • 논리 벡터에 대한 내용은 Logicals 페이지에서 계속 이어져요.
  • 문자열 작업은 Strings 두 장에서 다뤄요.
  • dplyr 함수들은 이름 구분자로 _를 쓰므로 na.rm 대신 na_rm처럼 쓰는 경우가 있어요.