본문 바로가기
R 프로그래밍/R advance

[R데이터다루기]데이터 변환

by 찐남 2021. 7. 18.
본 포스팅은 R for Data Science를 기반으로 작성되었습니다. 

 

1. 소개


시각화는 통찰력 생성을 위한 중요한 도구이지만 필요한 형식으로 데이터를 정확히 얻는 경우는 매우 드뭅니다. 그래서 시각화는 데이터 탐색이라고 많이 표현합니다. 데이터 작업을 좀 더 쉽게 하기 위해 변수의 이름을 바꾸거나 관측치를 재 정렬하고 싶을 때도 있습니다. 2013년에 뉴욕시에서 출발하는 항공편에서 dplyr 패키지와 새로운 data set을 사용하여 데이터를 변환하는 방법을 배워 보겠습니다.

 

 



 

1.1. 전제 조건


이 장에서 Tidyverse의 또 다른 핵심 패키지인 dplyr 패키지를 사용하는 방법에 대해 알아 보겠습니다. nycflights13 패키지의 데이터를 사용해서 주요 내용을 설명하고 데이터를 이해하는 데 도움이 되도록 ggplot2를 사용합니다. (ggplot2에 대해 자세히 알고 싶으시면, 데이터 시각화 포스팅을 참고하세요).

library(nycflights13)
library(tidyverse)


Tidyverse 패키지를 로드할 때 충돌 메시지에 주의하세요. dplyr 패키지가 R base의 일부 기능을 덮어써버립니다. dplyr패키지를 로드한 후 R의 기본 버전을 사용하려면 stats::filter(), stats::lag()와 같이 전체 이름을 사용해야 합니다.

 

1.2. nycflights13 데이터 설명


dplyr의 기본 데이터를 탐색하기 위해 nycflights13::flights를 사용합니다. 이 데이터 프레임에는 2013년에 뉴욕에서 출발한 모든 336,776개의 항공편이 포함되어 있습니다.


이 데이터 프레임이 과거에 사용했을 수 있는 다른 데이터 프레임의 형태와 약간 다르게 출력됨을 알 수 있습니다. 한 화면에 맞는 처음 몇 개의 행과 모든 열만 표시합니다. (전체 데이터 세트를 보려면 RStudio 뷰어에서 데이터 세트를 여는 View(flights)를 실행할 수 있습니다.) tibble이라는 형태의 데이터 프레임으로 일반 데이터 프레임과는 다르게 보이는 것입니다. Tibble 데이터 프레임에 대해서 더 자세히 알고 싶으시면, tibble 포스팅을 참고하시면 됩니다. 열 이름 아래에 3자(또는 4자)의 약어 행을 볼 수 있습니다. 이것은 각 변수의 유형을 설명합니다.

  • int는 정수를 나타냅니다.
  • dbl은 double 또는 실수를 나타냅니다.
  • chr은 문자형 벡터 또는 문자열을 나타냅니다.
  • dttm은 날짜-시간(날짜 + 시간)을 나타냅니다.


이 데이터 세트에서 사용되지 않는 세 가지 다른 유형의 변수가 있지만 나중에 배우도록 하겠습니다.

  • lgl은 TRUE 또는 FALSE만 포함하는 논리 벡터를 나타냅니다.
  • fctr은 R이 고정 가능한 값을 가진 범주형 변수를 나타내는 데 사용하는 요인(factor)을 나타냅니다.
  • date는 날짜를 나타냅니다.

 

1.3. dplyr 패키지 기초


이 장에서는 대부분의 데이터 변환 문제를 해결할 수 있는 5가지 주요 dplyr 기능을 배울 것입니다.

  • 값으로 관찰을 선택합니다(filter()).
  • 행 재정렬(arrange())
  • 이름으로 변수를 선택합니다(select()).
  • 기존 변수의 함수로 새 변수를 만듭니다(mutate()).
  • 많은 값을 하나의 요약으로 축소합니다(summarise()).


이 함수들은 모두 group_by() 함수와 함께 사용할 수 있고, 이는 각 함수의 범위를 전체 데이터 세트에서 작동하는 것에서 그룹별로 작동하는 것으로 변경합니다. 이 6가지 함수는 데이터 조작 언어에 대한 동사를 제공합니다.

모든 동사는 비슷하게 작동합니다.

  1. 첫 번째 인수는 데이터 프레임입니다.
  2. 후속 인수는 변수 이름(따옴표 제외)을 사용하여 데이터 프레임으로 수행할 작업을 설명합니다.
  3. 결과는 새 데이터 프레임입니다.


이러한 속성을 함께 사용하면 여러 간단한 단계를 쉽게 연결하여 복잡한 결과를 얻을 수 있습니다. 이 동사가 어떻게 작동하는지 살펴보겠습니다.

 

2. filter() 함수


filter() 함수는 값을 기반으로 관찰의 하위 집합을 만들 수 있습니다. 첫 번째 인수는 데이터 프레임의 이름입니다. 두 번째 및 후속 인수는 데이터 프레임을 필터링하는 표현식입니다. 예를 들어 다음을 사용하여 1월 1일의 모든 항공편을 선택할 수 있습니다.


해당 코드 줄을 실행하면 dplyr 패키지의 필터링 작업을 실행하고, 그 결과를 새 데이터 프레임으로 반환합니다. dplyr 패키지는 작업 결과로 데이터 프레임이 수정되지 않으므로 결과를 저장하려면 할당 연산자 <-를 사용해야 합니다.

jan1 <- filter(flights, month == 1, day == 1)


R은 결과를 출력하거나 변수에 저장합니다. 둘 다 수행하려면 괄호로 할당을 감쌀 수 있습니다.

(dec25 <- filter(flights, month == 12, day == 25))

 

 

2.1. 비교


필터링을 효과적으로 사용하려면 비교 연산자를 사용하여 원하는 관측값을 선택하는 방법을 알아야 합니다. R은 >, >=, <, <=, !=(같지 않음) 및 ==(같음)와 같은 표준을 제공합니다. R로 시작할 때 가장 쉬운 실수는 동등성을 테스트할 때 == 대신 =를 사용하는 것입니다. 이 경우 정보 오류가 발생합니다.


==를 사용할 때 발생할 수 있는 또 다른 문제가 있습니다. 부동 소수점 숫자. 이 결과를 보면 잠시 놀랄 수 있습니다.


컴퓨터는 유한한 정밀도 산술을 사용하므로(무한한 자릿수를 저장할 수 없습니다) 보는 모든 숫자는 근사치임을 기억하십시오. ==에 의존하는 대신 Near()를 사용하십시오.

 

2.2. 논리 연산자


filter()에 대한 여러 인수는 "and"와 결합됩니다. 행이 출력에 포함되려면 모든 표현식이 true여야 합니다. 다른 유형의 조합의 경우 부울 연산자를 직접 사용해야 합니다. &는 "그리고"입니다. | "또는"이고 ! 아니다"입니다. 아래 그림을 보면 명확이 이해하실 수 있습니다.


다음 코드는 11월 또는 12월에 출발한 모든 항공편을 찾습니다.

filter(flights, month == 11 | month == 12)


작업 순서는 영어처럼 작동하지 않습니다. 즉, filter(flights, month == (11 | 12))를 작성할 수 없습니다. 문자 그대로 "11월 또는 12월에 출발한 모든 항공편 찾기"로 해석할 수 있습니다. 대신 11 혹은 12월과 같은 모든 월을 찾아 TRUE로 평가되는 표현식입니다. 이 예에서 처럼 숫자 콘텍스트에서 TRUE는 1이 되므로 11월이나 12월이 아닌 1월의 모든 항공편을 찾습니다. 상당히 혼란스럽습니다. 이 문제에 대한 유용한 약칭은 x %in% y입니다. 이것은 x가 y의 값 중 하나인 모든 행을 선택합니다. 위의 코드를 아래처럼 다시 작성할 수 있습니다.

nov_dec <- filter(flights, month %in% c(11, 12))


때로는 드모르간의 법칙(De Morgan’s law)을 기억하여 복잡한 부분 집합을 단순화할 수 있습니다. 즉, !(x & y)는 !x | !y 및 !(x | y)는 !x 및 !y와 동일합니다. 예를 들어, 도착 또는 출발 시 2시간 이상 지연되지 않은 항공편을 찾으려면 다음 두 필터 중 하나를 사용할 수 있습니다.

filter(flights, !(arr_delay > 120 | dep_delay > 120))
filter(flights, arr_delay <= 120, dep_delay <= 120)


& 및 |와 마찬가지로 R에도 && 및 ||가 있습니다. 조건부 실행에서 알아보도록 하겠습니다. filter()에서 복잡한 다중 파트 표현식을 사용하기 시작할 때마다 대신 명시적 변수로 만드는 것이 좋습니다. 그러면 작업을 훨씬 쉽게 확인할 수 있습니다. 새로운 변수를 만드는 방법을 곧 배우게 될 것입니다.

2.3. 결측치


비교를 어렵게 만들 수 있는 R의 중요한 기능 중 하나는 결측 값 또는 NA("사용할 수 없음")입니다. NA는 알 수 없는 값을 나타내므로 누락된 값은 "전염적"입니다. 알 수 없는 값을 포함하는 거의 모든 작업의 결과도 알 수 없습니다.


가장 혼란스러운 결과는 아래와 같습니다.


이것이 왜 사실인지 이해하는 것은 좀 더 문맥을 통해 이해하는 것이 가장 쉽습니다.

# Let x be Mary's age. We don't know how old she is.
x <- NA

# Let y be John's age. We don't know how old he is.
y <- NA

# Are John and Mary the same age?
x == y
#> [1] NA
# We don't know!


값이 누락되었는지 확인하려면 is.na()를 사용하십시오.

is.na(x)
#> [1] TRUE


filter()는 조건이 TRUE인 행만 포함합니다. FALSE 및 NA 값을 모두 제외합니다. 누락된 값을 유지하려면 명시적으로 요청하십시오.

df <- tibble(x = c(1, NA, 3))
filter(df, x > 1)
#> # A tibble: 1 x 1
#> x
#> <dbl>
#> 1 3
filter(df, is.na(x) | x > 1)
#> # A tibble: 2 x 1
#> x
#> <dbl>
#> 1 NA
#> 2 3

 

 



 

3. arrange()


Arrange() 함수는 행을 선택하는 대신 순서를 변경한다는 점을 제외하고 filter()와 유사하게 작동합니다. 데이터 프레임과 열 이름 세트(또는 더 복잡한 표현식)가 필요합니다. 두 개 이상의 열 이름을 제공하는 경우 각 추가 열은 이전 열 값의 연결을 끊는 데 사용됩니다.

arrange(flights, year, month, day)
#> # A tibble: 336,776 x 19
#> year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
#> <int> <int> <int> <int> <int> <dbl> <int> <int>
#> 1 2013 1 1 517 515 2 830 819
#> 2 2013 1 1 533 529 4 850 830
#> 3 2013 1 1 542 540 2 923 850
#> 4 2013 1 1 544 545 -1 1004 1022
#> 5 2013 1 1 554 600 -6 812 837
#> 6 2013 1 1 554 558 -4 740 728
#> # … with 336,770 more rows, and 11 more variables: arr_delay <dbl>,
#> # carrier <chr>, flight <int>, tailnum <chr>, origin <chr>, dest <chr>,
#> # air_time <dbl>, distance <dbl>, hour <dbl>, minute <dbl>, time_hour <dttm>


desc() 함수를 사용하여 열을 내림차순으로 재정렬합니다.

arrange(flights, desc(dep_delay))
#> # A tibble: 336,776 x 19
#> year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
#> <int> <int> <int> <int> <int> <dbl> <int> <int>
#> 1 2013 1 9 641 900 1301 1242 1530
#> 2 2013 6 15 1432 1935 1137 1607 2120
#> 3 2013 1 10 1121 1635 1126 1239 1810
#> 4 2013 9 20 1139 1845 1014 1457 2210
#> 5 2013 7 22 845 1600 1005 1044 1815
#> 6 2013 4 10 1100 1900 960 1342 2211
#> # … with 336,770 more rows, and 11 more variables: arr_delay <dbl>,
#> # carrier <chr>, flight <int>, tailnum <chr>, origin <chr>, dest <chr>,
#> # air_time <dbl>, distance <dbl>, hour <dbl>, minute <dbl>, time_hour <dttm>


결측치는 항상 끝에 정렬됩니다.

df <- tibble(x = c(5, 2, NA))
arrange(df, x)
#> # A tibble: 3 x 1
#> x
#> <dbl>
#> 1 2
#> 2 5
#> 3 NA
arrange(df, desc(x))
#> # A tibble: 3 x 1
#> x
#> <dbl>
#> 1 5
#> 2 2
#> 3 NA

 

4. select()


수백 또는 수천 개의 변수가 있는 데이터 세트를 얻는 것은 흔한 일입니다. 이 경우 첫 번째 과제는 종종 실제로 관심이 있는 몇 개의 변수로 좁히는 것입니다. select() 함수를 사용하면 변수 이름을 기반으로 하는 작업을 사용하여 유용한 하위 집합을 빠르게 확대할 수 있습니다. select() 함수는 19개의 변수로 그 수가 많진 않지만, 그냥 사용해 보도록 하겠습니다.

# Select columns by name
select(flights, year, month, day)
#> # A tibble: 336,776 x 3
#> year month day
#> <int> <int> <int>
#> 1 2013 1 1
#> 2 2013 1 1
#> 3 2013 1 1
#> 4 2013 1 1
#> 5 2013 1 1
#> 6 2013 1 1
#> # … with 336,770 more rows
# Select all columns between year and day (inclusive)
select(flights, year:day)
#> # A tibble: 336,776 x 3
#> year month day
#> <int> <int> <int>
#> 1 2013 1 1
#> 2 2013 1 1
#> 3 2013 1 1
#> 4 2013 1 1
#> 5 2013 1 1
#> 6 2013 1 1
#> # … with 336,770 more rows
# Select all columns except those from year to day (inclusive)
select(flights, -(year:day))
#> # A tibble: 336,776 x 16
#> dep_time sched_dep_time dep_delay arr_time sched_arr_time arr_delay carrier
#> <int> <int> <dbl> <int> <int> <dbl> <chr>
#> 1 517 515 2 830 819 11 UA
#> 2 533 529 4 850 830 20 UA
#> 3 542 540 2 923 850 33 AA
#> 4 544 545 -1 1004 1022 -18 B6
#> 5 554 600 -6 812 837 -25 DL
#> 6 554 558 -4 740 728 12 UA
#> # … with 336,770 more rows, and 9 more variables: flight <int>, tailnum <chr>,
#> # origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>, hour <dbl>,
#> # minute <dbl>, time_hour <dttm>


select() 함수 내에서 실용적으로 사용할 수 있는 여러 도우미 함수들이 있습니다.

  • starts_with("abc"): "abc"로 시작하는 이름과 일치합니다.
  • end_with("xyz"): "xyz"로 끝나는 이름과 일치합니다.
  • contains("ijk"): "ijk"를 포함하는 이름과 일치합니다.
  • match("(.)\\1"): 정규표현식과 일치하는 변수를 선택합니다. 이것은 반복되는 문자를 포함하는 모든 변수를 선택합니다. 문자열의 정규표현식에 대해서는 나중에 더 배워 보도록 하겠습니다.
  • num_range("x", 1:3): x1, x2 및 x3과 일치합니다.


더 자세한 내용은 ?선택을 참조하십시오. select() 함수는 변수의 이름을 바꾸는 데 사용할 수 있지만 select문에 언급되지 않은 모든 변수를 삭제하기 때문에 거의 유용하지 않습니다. 대신 명시적으로 언급되지 않은 모든 변수를 유지하는 select()의 변형인 rename()을 사용하시는 것이 더 좋습니다.

rename(flights, tail_num = tailnum)
#> # A tibble: 336,776 x 19
#> year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
#> <int> <int> <int> <int> <int> <dbl> <int> <int>
#> 1 2013 1 1 517 515 2 830 819
#> 2 2013 1 1 533 529 4 850 830
#> 3 2013 1 1 542 540 2 923 850
#> 4 2013 1 1 544 545 -1 1004 1022
#> 5 2013 1 1 554 600 -6 812 837
#> 6 2013 1 1 554 558 -4 740 728
#> # … with 336,770 more rows, and 11 more variables: arr_delay <dbl>,
#> # carrier <chr>, flight <int>, tail_num <chr>, origin <chr>, dest <chr>,
#> # air_time <dbl>, distance <dbl>, hour <dbl>, minute <dbl>, time_hour <dttm>


또 다른 옵션은 everything() 도우미와 함께 select()를 사용하는 것입니다. 이것은 데이터 프레임의 시작 부분으로 이동하려는 소수의 변수가 있는 경우에 유용합니다.

select(flights, time_hour, air_time, everything())
#> # A tibble: 336,776 x 19
#> time_hour air_time year month day dep_time sched_dep_time
#> <dttm> <dbl> <int> <int> <int> <int> <int>
#> 1 2013-01-01 05:00:00 227 2013 1 1 517 515
#> 2 2013-01-01 05:00:00 227 2013 1 1 533 529
#> 3 2013-01-01 05:00:00 160 2013 1 1 542 540
#> 4 2013-01-01 05:00:00 183 2013 1 1 544 545
#> 5 2013-01-01 06:00:00 116 2013 1 1 554 600
#> 6 2013-01-01 05:00:00 150 2013 1 1 554 558
#> # … with 336,770 more rows, and 12 more variables: dep_delay <dbl>,
#> # arr_time <int>, sched_arr_time <int>, arr_delay <dbl>, carrier <chr>,
#> # flight <int>, tailnum <chr>, origin <chr>, dest <chr>, distance <dbl>,
#> # hour <dbl>, minute <dbl>

 

 



 

 

5. mutate()


기존 열 집합을 선택하는 것 외에도 기존 열에 새 열을 추가하는 것이 필요할 때도 있습니다. 그것이 mutate() 함수의 역할입니다. mutate() 함수는 항상 데이터 세트의 끝에 새 열을 추가하므로 새 변수를 볼 수 있도록 변수의 개수가 적은 데이터 세트를 만드는 것으로 시작합니다. RStudio에서 모든 열을 보는 가장 쉬운 방법은 View()입니다.

flights_sml <- select(flights,
year:day,
ends_with("delay"),
distance,
air_time
)
mutate(flights_sml,
gain = dep_delay - arr_delay,
speed = distance / air_time * 60
)
#> # A tibble: 336,776 x 9
#> year month day dep_delay arr_delay distance air_time gain speed
#> <int> <int> <int> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 2013 1 1 2 11 1400 227 -9 370.
#> 2 2013 1 1 4 20 1416 227 -16 374.
#> 3 2013 1 1 2 33 1089 160 -31 408.
#> 4 2013 1 1 -1 -18 1576 183 17 517.
#> 5 2013 1 1 -6 -25 762 116 19 394.
#> 6 2013 1 1 -4 12 719 150 -16 288.
#> # … with 336,770 more rows


아래와 같이 방금 생성한 열을 참조할 수 있습니다.

mutate(flights_sml,
gain = dep_delay - arr_delay,
hours = air_time / 60,
gain_per_hour = gain / hours
)
#> # A tibble: 336,776 x 10
#> year month day dep_delay arr_delay distance air_time gain hours
#> <int> <int> <int> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 2013 1 1 2 11 1400 227 -9 3.78
#> 2 2013 1 1 4 20 1416 227 -16 3.78
#> 3 2013 1 1 2 33 1089 160 -31 2.67
#> 4 2013 1 1 -1 -18 1576 183 17 3.05
#> 5 2013 1 1 -6 -25 762 116 19 1.93
#> 6 2013 1 1 -4 12 719 150 -16 2.5
#> # … with 336,770 more rows, and 1 more variable: gain_per_hour <dbl>


새 변수만 유지하려면 transmute() 함수를 사용하십시오.

transmute(flights,
gain = dep_delay - arr_delay,
hours = air_time / 60,
gain_per_hour = gain / hours
)
#> # A tibble: 336,776 x 3
#> gain hours gain_per_hour
#> <dbl> <dbl> <dbl>
#> 1 -9 3.78 -2.38
#> 2 -16 3.78 -4.23
#> 3 -31 2.67 -11.6
#> 4 17 3.05 5.57
#> 5 19 1.93 9.83
#> 6 -16 2.5 -6.4
#> # … with 336,770 more rows

 

5.1. 유용한 생성 기능


mutate() 함수와 함께 사용할 수 있는 새 변수를 생성하기 위한 많은 함수가 있습니다. 핵심 속성은 함수가 벡터화되어야 한다는 것입니다. 값의 벡터를 입력으로 취해야 하며 출력과 동일한 수의 값을 가진 벡터를 반환해야 합니다. 사용할 수 있는 모든 기능을 나열할 수는 없지만 다음은 자주 유용하게 사용할 수 있는 기능입니다.

  • 산술 연산자: +, -, *, /, ^. : 소위 "재활용 규칙(recycling rules)"을 사용하여 벡터화됩니다. 한 매개변수가 다른 매개변수보다 짧으면 자동으로 같은 길이로 확장됩니다. 이것은 인수 중 하나가 단일 숫자일 때 가장 유용합니다 (air_time / 60, hours * 60 + minute 등). 산술 연산자는 나중에 배우게 될 집계 함수와 함께 사용할 때도 유용합니다. 예를 들어, x / sum(x)은 합계의 비율을 계산하고 y - mean(y)은 평균과의 차이입니다.
  • 모듈식 산술: %/%(정수 나누기) 및 %%(나머지), x == y * (x %/% y) + (x %% y). 모듈식 산술은 정수를 여러 조각으로 나눌 수 있기 때문에 편리한 도구입니다. 예를 들어, flight 데이터 세트에서 다음을 사용하여 dep_time에서 시간과 분을 계산할 수 있습니다.

 

transmute(flights,
dep_time,
hour = dep_time %/% 100,
minute = dep_time %% 100
)
#> # A tibble: 336,776 x 3
#> dep_time hour minute
#> <int> <dbl> <dbl>
#> 1 517 5 17
#> 2 533 5 33
#> 3 542 5 42
#> 4 544 5 44
#> 5 554 5 54
#> 6 554 5 54
#> # … with 336,770 more rows

 

  • Logs: log(), log2(), log10(). 로그는 다양한 크기의 데이터를 처리하는 데 매우 유용한 변환입니다. 또한 곱셈 관계를 덧셈으로 변환하는데, 이는 모델링에서 다시 다룰 기능입니다. 다른 모든 조건이 동일하면 해석하기 쉽기 때문에 log2()를 사용하는 것이 좋습니다. 로그 척도에서 1의 차이는 원래 척도에서 2배에 해당하고 -1의 차이는 반감에 해당합니다.
  • Offsets: Lead() 및 lag() 함수를 사용하면 선행 또는 후행 값을 참조할 수 있습니다. 이를 통해 실행 차이(예: x - lag(x))를 계산하거나 값이 변경되는 시점(x != lag(x))을 찾을 수 있습니다. 곧 배우게 될 group_by() 함수와 함께 사용하면 가장 유용합니다.

 

(x <- 1:10)
#> [1] 1 2 3 4 5 6 7 8 9 10
lag(x)
#> [1] NA 1 2 3 4 5 6 7 8 9
lead(x)
#> [1] 2 3 4 5 6 7 8 9 10 NA

 

  • Cumulative and rolling aggregates: R은 합계, 곱, 최솟값 및 최댓값을 실행하는 함수를 제공합니다. cumsum(), cumprod(), cummin(), cummax(); dplyr는 누적 평균에 대해 cummean()을 제공합니다. 롤링 집계(즉, 롤링 창에서 계산된 합계)가 필요한 경우 RcppRoll 패키지를 사용해 보세요.

 

x
#> [1] 1 2 3 4 5 6 7 8 9 10
cumsum(x)
#> [1] 1 3 6 10 15 21 28 36 45 55
cummean(x)
#> [1] 1.0 1.5 2.0 2.5 3.0 3.5 4.0 4.5 5.0 5.5

 

  • 이전에 배운 논리적 비교, <, <=, >, >=, != 및 == . 복잡한 논리 연산 시퀀스를 수행하는 경우 각 단계가 예상대로 작동하는지 확인할 수 있도록 중간 값을 새 변수에 저장 후 확인하면서 계산하는 것이 좋습니다.
  • Ranking: 여러 ranking 함수가 있지만 min_rank() 함수부터 보도록 하겠습니다. 가장 일반적인 유형의 순위(예: 1위, 2위, 2위, 4위)를 수행합니다. 기본값은 가장 작은 값에 작은 순위를 제공합니다. desc(x)를 사용하면 가장 큰 값에 가장 작은 순위를 지정할 수 있습니다.

 

y <- c(1, 2, 2, NA, 3, 4)
min_rank(y)
#> [1] 1 2 2 NA 4 5
min_rank(desc(y))
#> [1] 5 3 3 NA 2 1


min_rank() 함수가 필요한 작업을 수행하지 않으면 row_number(), density_rank(), percent_rank(), cume_dist(), ntile() 등의 변형 함수도 있습니다. 자세한 내용은 도움말 페이지를 참조하시면 됩니다.

row_number(y)
#> [1] 1 2 3 NA 4 5
dense_rank(y)
#> [1] 1 2 2 NA 3 4
percent_rank(y)
#> [1] 0.00 0.25 0.25 NA 0.75 1.00
cume_dist(y)
#> [1] 0.2 0.6 0.6 NA 0.8 1.0

 

 



 

6. summarise()


마지막으로 summarise()입니다. 데이터 프레임을 단일 행으로 축소합니다.

summarise(flights, delay = mean(dep_delay, na.rm = TRUE))
#> # A tibble: 1 x 1
#> delay
#> <dbl>
#> 1 12.6


summarise() 함수는 group_by()와 함께 사용하지 않는 한 별로 유용하지 않습니다. 이렇게 하면 전체 데이터 세트에서 개별 그룹으로 분석 단위가 변경됩니다. 그런 다음 그룹화된 데이터 프레임에서 dplyr 동사를 사용하면 "그룹별로" 자동 적용됩니다. 예를 들어 날짜별로 그룹화된 데이터 프레임에 정확히 동일한 코드를 적용한 경우 날짜당 평균 지연을 얻습니다.

by_day <- group_by(flights, year, month, day)
summarise(by_day, delay = mean(dep_delay, na.rm = TRUE))
#> `summarise()` regrouping output by 'year', 'month' (override with `.groups` argument)
#> # A tibble: 365 x 4
#> # Groups: year, month [12]
#> year month day delay
#> <int> <int> <int> <dbl>
#> 1 2013 1 1 11.5
#> 2 2013 1 2 13.9
#> 3 2013 1 3 11.0
#> 4 2013 1 4 8.95
#> 5 2013 1 5 5.73
#> 6 2013 1 6 7.15
#> # … with 359 more rows


group_by() 함수 및 summarise() 함수는 dplyr(그룹화된 요약)로 함께 작업할 때 가장 일반적으로 사용할 도구 중 하나를 제공합니다. 그러나 더 진행하기 전에 강력한 새 아이디어인 파이프를 도입해야 합니다.

6.1. 파이프로 여러 작업 결합


각 위치에 대한 거리와 평균 지연 간의 관계를 탐색을 해보도록 하겠습니다. dplyr에 대해 알고 있는 것을 사용하여 다음과 같은 코드를 작성할 수 있습니다.

by_dest <- group_by(flights, dest)
delay <- summarise(by_dest,
count = n(),
dist = mean(distance, na.rm = TRUE),
delay = mean(arr_delay, na.rm = TRUE)
)
#> `summarise()` ungrouping output (override with `.groups` argument)
delay <- filter(delay, count > 20, dest != "HNL")

# It looks like delays increase with distance up to ~750 miles
# and then decrease. Maybe as flights get longer there's more
# ability to make up delays in the air?
ggplot(data = delay, mapping = aes(x = dist, y = delay)) +
geom_point(aes(size = count), alpha = 1/3) +
geom_smooth(se = FALSE)
#> `geom_smooth()` using method = 'loess' and formula 'y ~ x'

 


이 데이터를 준비하는 세 단계가 있습니다.

  1. 목적지별로 항공편을 그룹화합니다.
  2. 거리, 평균 지연 및 비행 횟수를 계산하기 위해 요약합니다.
  3. 다음으로 가장 가까운 공항보다 거의 두 배 가까운 거리에 있는 호놀룰루 공항과 시끄러운 지점을 제거하기 위해 필터링합니다.

이 과정을 잘 보면, 스텝 중간중간에 데이터 프레임을 생성하여 이름을 부여해야 하기 때문에 작성하기 약간 불편합니다. 이름을 생성하는 것도 생각해야 하기 때문에 분석 속도가 느려집니다. 파이프(%>%)로 동일한 문제를 해결하는 또 다른 방법이 있습니다.

delays <- flights %>%
group_by(dest) %>%
summarise(
count = n(),
dist = mean(distance, na.rm = TRUE),
delay = mean(arr_delay, na.rm = TRUE)
) %>%
filter(count > 20, dest != "HNL")
#> `summarise()` ungrouping output (override with `.groups` argument)


이것은 코드를 더 쉽게 읽을 수 있습니다. 일련의 명령문으로 읽을 수 있습니다. 순서대로 그룹화, 요약 및 필터링을 수행합니다. 이 글에서 알 수 있듯이 코드를 읽을 때 %>%를 발음하는 좋은 방법은 "then"입니다. 그 배경에는 x %>% f(y)는 f(x, y)로 바뀌고 x %>% f(y) %>% g(z)는 g(f(x, y), z)로 바뀝니다. 파이프를 사용하여 왼쪽에서 오른쪽, 위에서 아래로 읽을 수 있는 방식으로 여러 작업을 다시 작성할 수 있습니다. 파이핑은 코드의 가독성을 상당히 향상시키기 때문에 앞으로 자주 사용할 것이며 파이프에서 더 자세히 다루겠습니다.

파이프 작업은 tidyverse 패키지에 속하는 주요 기준 중 하나입니다. 유일한 예외는 ggplot2 패키지입니다. ggplot2 패키지는 파이프 이전에 작성된 패키지입니다. 불행히도 파이프를 사용하는 ggplot2의 다음 반복인 ggvis는 아직 본격적인 사용 준비가 되지 않았습니다.

6.2. 결측치


위에서 사용한 na.rm 인수에 대해 궁금해했을 것입니다. 설정하지 않으면 어떻게 되나요?

flights %>%
group_by(year, month, day) %>%
summarise(mean = mean(dep_delay))
#> `summarise()` regrouping output by 'year', 'month' (override with `.groups` argument)
#> # A tibble: 365 x 4
#> # Groups: year, month [12]
#> year month day mean
#> <int> <int> <int> <dbl>
#> 1 2013 1 1 NA
#> 2 2013 1 2 NA
#> 3 2013 1 3 NA
#> 4 2013 1 4 NA
#> 5 2013 1 5 NA
#> 6 2013 1 6 NA
#> # … with 359 more rows


변수 mean 값이 모두 NA입니다. 집계 함수가 결측 값의 일반적인 규칙을 따르기 때문입니다. 입력에 결측치가 있으면 출력은 결측치가 됩니다. 다행히 모든 집계 함수에는 계산 전에 누락된 값을 제거하는 na.rm 인수가 있습니다.

flights %>%
group_by(year, month, day) %>%
summarise(mean = mean(dep_delay, na.rm = TRUE))
#> `summarise()` regrouping output by 'year', 'month' (override with `.groups` argument)
#> # A tibble: 365 x 4
#> # Groups: year, month [12]
#> year month day mean
#> <int> <int> <int> <dbl>
#> 1 2013 1 1 11.5
#> 2 2013 1 2 13.9
#> 3 2013 1 3 11.0
#> 4 2013 1 4 8.95
#> 5 2013 1 5 5.73
#> 6 2013 1 6 7.15
#> # … with 359 more rows


이 경우 결측 값이 취소된 항공편을 나타내는 경우 먼저 취소된 항공편을 제거하여 문제를 해결할 수도 있습니다. 다음 몇 가지 예에서 재사용할 수 있도록 이 데이터 세트를 저장합니다.

not_cancelled <- flights %>%
filter(!is.na(dep_delay), !is.na(arr_delay))

not_cancelled %>%
group_by(year, month, day) %>%
summarise(mean = mean(dep_delay))
#> `summarise()` regrouping output by 'year', 'month' (override with `.groups` argument)
#> # A tibble: 365 x 4
#> # Groups: year, month [12]
#> year month day mean
#> <int> <int> <int> <dbl>
#> 1 2013 1 1 11.4
#> 2 2013 1 2 13.7
#> 3 2013 1 3 10.9
#> 4 2013 1 4 8.97
#> 5 2013 1 5 5.73
#> 6 2013 1 6 7.15
#> # … with 359 more rows

 

6.3. Counts


집계를 수행할 때마다 항상 개수(n()) 또는 누락되지 않은 값의 개수(sum(!is.na(x)))를 포함하는 것이 좋습니다. 그렇게 하면 매우 적은 양의 데이터를 기반으로 결론을 도출하고 있지는 않은지 확인할 수 있습니다. 예를 들어, 평균 지연이 가장 높은 비행기(꼬리 번호로 식별)를 살펴보겠습니다.

delays <- not_cancelled %>%
group_by(tailnum) %>%
summarise(
delay = mean(arr_delay)
)
#> `summarise()` ungrouping output (override with `.groups` argument)

ggplot(data = delays, mapping = aes(x = delay)) +
geom_freqpoly(binwidth = 10)

 


평균 5시간(300분) 지연되는 비행기도 있습니다.

사실 스토리는 조금 더 상세합니다. 비행 횟수 대 평균 지연의 산점도를 그리면 더 많은 통찰력을 얻을 수 있습니다.

delays <- not_cancelled %>%
group_by(tailnum) %>%
summarise(
delay = mean(arr_delay, na.rm = TRUE),
n = n()
)
#> `summarise()` ungrouping output (override with `.groups` argument)

ggplot(data = delays, mapping = aes(x = n, y = delay)) +
geom_point(alpha = 1/10)

 


당연히 항공편이 거의 없을 때 평균 지연의 편차가 훨씬 더 큽니다. 이 플롯의 모양은 매우 특징이 있습니다. 평균(또는 기타 요약) 대 그룹 크기를 그릴 때마다 표본 크기가 증가함에 따라 변동이 감소하는 것을 볼 수 있습니다. 이러한 종류의 그림을 볼 때 가장 적은 수의 관측치를 가진 그룹을 필터링하는 것이 종종 유용하므로 가장 작은 그룹에서 패턴을 더 많이 볼 수 있고 극단적인 변동을 덜 볼 수 있습니다. 앞서 말한 내용은 아래 코드가 하는 일이며 ggplot2를 dplyr 흐름에 통합하기 위한 편리한 패턴을 보여줍니다. %>% 에서 +로 전환해야 하는 것이 약간 혼란스럽긴 하지만 일단 익숙해지면 상당히 편리합니다.

delays %>%
filter(n > 25) %>%
ggplot(mapping = aes(x = n, y = delay)) +
geom_point(alpha = 1/10)

 


이 유형의 패턴에는 또 다른 변형이 있음을 알 수 있습니다. 야구에서 타자들의 평균 성적이 타석 횟수와 어떤 관련이 있는지 살펴보겠습니다. 여기에서 Lahman 패키지의 데이터를 사용하여 모든 메이저 리그 야구 선수의 타율(안타 수/시도 수)을 계산합니다.

공을 칠 기회의 수(타석, ab로 측정)에 대해 타자의 기술(타율, ba로 측정)을 플롯 하면 두 가지 패턴이 표시됩니다.

  1. 위와 같이 더 많은 데이터 포인트를 얻을수록 집계의 변동이 줄어듭니다.
  2. 기술(ba)과 공을 칠 기회(ab) 사이에는 양의 상관관계가 있습니다. 이는 팀이 누가 경기에 참여할지 통제하고 분명히 최고의 선수를 선택하기 때문입니다.

 

# Convert to a tibble so it prints nicely
batting <- as_tibble(Lahman::Batting)

batters <- batting %>%
group_by(playerID) %>%
summarise(
ba = sum(H, na.rm = TRUE) / sum(AB, na.rm = TRUE),
ab = sum(AB, na.rm = TRUE)
)
#> `summarise()` ungrouping output (override with `.groups` argument)

batters %>%
filter(ab > 100) %>%
ggplot(mapping = aes(x = ab, y = ba)) +
geom_point() +
geom_smooth(se = FALSE)
#> `geom_smooth()` using method = 'gam' and formula 'y ~ s(x, bs = "cs")'

 


이것은 또한 순위에 중요한 영향을 미칩니다. desc(ba) 순으로 정렬하면 최고의 타율을 가진 사람들은 분명히 운이 좋은 사람이지 숙련된 사람이 아닙니다.

batters %>%
arrange(desc(ba))
#> # A tibble: 19,689 x 3
#> playerID ba ab
#> <chr> <dbl> <int>
#> 1 abramge01 1 1
#> 2 alanirj01 1 1
#> 3 alberan01 1 1
#> 4 banisje01 1 1
#> 5 bartocl01 1 1
#> 6 bassdo01 1 1
#> # … with 19,683 more rows

 

6.4. 유용한 요약 함수


R은 많은 유용한 요약 기능을 제공합니다.

  • 위치 측정: mean(x)을 사용했지만 median(x)도 유용합니다. 평균은 합을 길이로 나눈 값입니다. 중앙값은 x의 50%가 위에 있고 50%가 아래에 있는 값입니다.

집계를 논리적 부분 집합과 결합하는 것이 때때로 유용합니다. 부분 집합은 다음 포스팅에서 배워보도록 하겠습니다. 사용 가능성에 대한 예제만 참고하세요.

not_cancelled %>%
group_by(year, month, day) %>%
summarise(
avg_delay1 = mean(arr_delay),
avg_delay2 = mean(arr_delay[arr_delay > 0]) # the average positive delay
)
#> `summarise()` regrouping output by 'year', 'month' (override with `.groups` argument)
#> # A tibble: 365 x 5
#> # Groups: year, month [12]
#> year month day avg_delay1 avg_delay2
#> <int> <int> <int> <dbl> <dbl>
#> 1 2013 1 1 12.7 32.5
#> 2 2013 1 2 12.7 32.0
#> 3 2013 1 3 5.73 27.7
#> 4 2013 1 4 -1.93 28.3
#> 5 2013 1 5 -1.53 22.6
#> 6 2013 1 6 4.24 24.4
#> # … with 359 more rows

 

  • 확산 측정: sd(x), IQR(x), mad(x). 제곱 평균, 제곱근 편차 또는 표준 편차 sd(x)는 산포의 표준 측도입니다. 사분위수 범위 IQR(x) 및 중앙값 절대 편차 mad(x)는 이상치가 있는 경우 더 유용할 수 있는 강력한 대안 통계량입니다.

 

# Why is distance to some destinations more variable than to others?
not_cancelled %>%
group_by(dest) %>%
summarise(distance_sd = sd(distance)) %>%
arrange(desc(distance_sd))
#> `summarise()` ungrouping output (override with `.groups` argument)
#> # A tibble: 104 x 2
#> dest distance_sd
#> <chr> <dbl>
#> 1 EGE 10.5
#> 2 SAN 10.4
#> 3 SFO 10.2
#> 4 HNL 10.0
#> 5 SEA 9.98
#> 6 LAS 9.91
#> # … with 98 more rows

 

  • 순위 측정: min(x), quantile(x, 0.25), max(x). 분위수는 중앙값의 일반화입니다. 예를 들어, quantile(x, 0.25)는 값의 25%보다 크고 나머지 75%보다 작은 x 값을 찾습니다.

 

# When do the first and last flights leave each day?
not_cancelled %>%
group_by(year, month, day) %>%
summarise(
first = min(dep_time),
last = max(dep_time)
)
#> `summarise()` regrouping output by 'year', 'month' (override with `.groups` argument)
#> # A tibble: 365 x 5
#> # Groups: year, month [12]
#> year month day first last
#> <int> <int> <int> <int> <int>
#> 1 2013 1 1 517 2356
#> 2 2013 1 2 42 2354
#> 3 2013 1 3 32 2349
#> 4 2013 1 4 25 2358
#> 5 2013 1 5 14 2357
#> 6 2013 1 6 16 2355
#> # … with 359 more rows

 

  • 위치 측정: 첫 번째(x), n번째(x, 2), 마지막(x). 이는 x[1], x[2], x[length(x)]와 유사하게 작동하지만 해당 위치가 존재하지 않는 경우 기본값을 설정할 수 있습니다. 다시 말해서, 두 개의 요소만 있는 그룹에서 세 번째 요소를 가져오려고 합니다. 예를 들어, 매일 첫출발과 마지막 출발을 찾을 수 있습니다.

 

not_cancelled %>%
group_by(year, month, day) %>%
summarise(
first_dep = first(dep_time),
last_dep = last(dep_time)
)
#> `summarise()` regrouping output by 'year', 'month' (override with `.groups` argument)
#> # A tibble: 365 x 5
#> # Groups: year, month [12]
#> year month day first_dep last_dep
#> <int> <int> <int> <int> <int>
#> 1 2013 1 1 517 2356
#> 2 2013 1 2 42 2354
#> 3 2013 1 3 32 2349
#> 4 2013 1 4 25 2358
#> 5 2013 1 5 14 2357
#> 6 2013 1 6 16 2355
#> # … with 359 more rows


이러한 기능은 순위 필터링을 보완합니다. 필터링은 각 관측치가 별도의 행에 있는 모든 변수를 제공합니다.

not_cancelled %>%
group_by(year, month, day) %>%
mutate(r = min_rank(desc(dep_time))) %>%
filter(r %in% range(r))
#> # A tibble: 770 x 20
#> # Groups: year, month, day [365]
#> year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
#> <int> <int> <int> <int> <int> <dbl> <int> <int>
#> 1 2013 1 1 517 515 2 830 819
#> 2 2013 1 1 2356 2359 -3 425 437
#> 3 2013 1 2 42 2359 43 518 442
#> 4 2013 1 2 2354 2359 -5 413 437
#> 5 2013 1 3 32 2359 33 504 442
#> 6 2013 1 3 2349 2359 -10 434 445
#> # … with 764 more rows, and 12 more variables: arr_delay <dbl>, carrier <chr>,
#> # flight <int>, tailnum <chr>, origin <chr>, dest <chr>, air_time <dbl>,
#> # distance <dbl>, hour <dbl>, minute <dbl>, time_hour <dttm>, r <int>

 

  • count: 인수를 사용하지 않고 현재 그룹의 크기를 반환하는 n()을 보았습니다. 결측 값이 아닌 값의 수를 계산하려면 sum(!is.na(x))를 사용하시면 됩니다. 고유한(고유한) 값의 수를 계산하려면 n_distinct(x)를 사용하십시오.

 

# Which destinations have the most carriers?
not_cancelled %>%
group_by(dest) %>%
summarise(carriers = n_distinct(carrier)) %>%
arrange(desc(carriers))
#> `summarise()` ungrouping output (override with `.groups` argument)
#> # A tibble: 104 x 2
#> dest carriers
#> <chr> <int>
#> 1 ATL 7
#> 2 BOS 7
#> 3 CLT 7
#> 4 ORD 7
#> 5 TPA 7
#> 6 AUS 6
#> # … with 98 more rows


count는 매우 유용하여 dplyr 패키지를 활용하여 원하고자 하는 모든 행위가 count인 경우 아래와 같이 간단히 표현 가능합니다.

not_cancelled %>%
count(dest)
#> # A tibble: 104 x 2
#> dest n
#> <chr> <int>
#> 1 ABQ 254
#> 2 ACK 264
#> 3 ALB 418
#> 4 ANC 8
#> 5 ATL 16837
#> 6 AUS 2411
#> # … with 98 more rows


선택적으로 가중치 변수를 제공할 수 있습니다. 예를 들어, 비행기가 비행한 총 마일 수를 "계산"(합계)할 수 있습니다.

not_cancelled %>%
count(tailnum, wt = distance)
#> # A tibble: 4,037 x 2
#> tailnum n
#> <chr> <dbl>
#> 1 D942DN 3418
#> 2 N0EGMQ 239143
#> 3 N10156 109664
#> 4 N102UW 25722
#> 5 N103US 24619
#> 6 N104UW 24616
#> # … with 4,031 more rows

 

  • 논리 값의 개수와 비율: sum(x > 10), mean(y == 0). 숫자 함수와 함께 사용하면 TRUE는 1로, FALSE는 0으로 변환됩니다. 이것은 sum() 및 mean()을 매우 유용하게 만듭니다. sum(x)은 x의 TRUE 수를 제공하고 mean(x)은 비율을 제공합니다.

 

# How many flights left before 5am? (these usually indicate delayed
# flights from the previous day)
not_cancelled %>%
group_by(year, month, day) %>%
summarise(n_early = sum(dep_time < 500))
#> `summarise()` regrouping output by 'year', 'month' (override with `.groups` argument)
#> # A tibble: 365 x 4
#> # Groups: year, month [12]
#> year month day n_early
#> <int> <int> <int> <int>
#> 1 2013 1 1 0
#> 2 2013 1 2 3
#> 3 2013 1 3 4
#> 4 2013 1 4 3
#> 5 2013 1 5 3
#> 6 2013 1 6 2
#> # … with 359 more rows

# What proportion of flights are delayed by more than an hour?
not_cancelled %>%
group_by(year, month, day) %>%
summarise(hour_prop = mean(arr_delay > 60))
#> `summarise()` regrouping output by 'year', 'month' (override with `.groups` argument)
#> # A tibble: 365 x 4
#> # Groups: year, month [12]
#> year month day hour_prop
#> <int> <int> <int> <dbl>
#> 1 2013 1 1 0.0722
#> 2 2013 1 2 0.0851
#> 3 2013 1 3 0.0567
#> 4 2013 1 4 0.0396
#> 5 2013 1 5 0.0349
#> 6 2013 1 6 0.0470
#> # … with 359 more rows

 

6.5. 여러 변수로 그룹화


여러 변수를 기준으로 그룹화하면 각 요약은 그룹화의 수준이 한 단계씩 벗겨집니다. 이렇게 하면 데이터 세트를 점진적으로 쉽게 롤업 할 수 있습니다.

daily <- group_by(flights, year, month, day)
(per_day <- summarise(daily, flights = n()))
#> `summarise()` regrouping output by 'year', 'month' (override with `.groups` argument)
#> # A tibble: 365 x 4
#> # Groups: year, month [12]
#> year month day flights
#> <int> <int> <int> <int>
#> 1 2013 1 1 842
#> 2 2013 1 2 943
#> 3 2013 1 3 914
#> 4 2013 1 4 915
#> 5 2013 1 5 720
#> 6 2013 1 6 832
#> # … with 359 more rows
(per_month <- summarise(per_day, flights = sum(flights)))
#> `summarise()` regrouping output by 'year' (override with `.groups` argument)
#> # A tibble: 12 x 3
#> # Groups: year [1]
#> year month flights
#> <int> <int> <int>
#> 1 2013 1 27004
#> 2 2013 2 24951
#> 3 2013 3 28834
#> 4 2013 4 28330
#> 5 2013 5 28796
#> 6 2013 6 28243
#> # … with 6 more rows
(per_year <- summarise(per_month, flights = sum(flights)))
#> `summarise()` ungrouping output (override with `.groups` argument)
#> # A tibble: 1 x 2
#> year flights
#> <int> <int>
#> 1 2013 336776


요약을 점진적으로 롤업 할 때 주의하세요. 합과 개수에 대해서는 괜찮지만 가중 평균과 분산에 대해 생각해야 하고 중앙값과 같은 순위 기반 통계에 대해 정확히 수행할 수 없습니다. 즉, 그룹별 합계의 합계는 전체 합계이지만 그룹별 중앙값의 중앙값은 전체 중앙값이 아닙니다.

6.6. 그룹 해체


그룹화를 제거하고 그룹화되지 않은 데이터에 대한 작업으로 돌아가려면 ungroup()을 사용하시면 됩니다.

daily %>%
ungroup() %>% # no longer grouped by date
summarise(flights = n()) # all flights
#> # A tibble: 1 x 1
#> flights
#> <int>
#> 1 336776

 

 



 

7. 그룹화된 돌연변이(및 필터)


그룹화는 summarise() 함수와 함께 사용할 때 가장 유용하지만 mutate() 및 filter()를 사용하여 편리한 작업을 수행할 수도 있습니다.

  • 각 그룹의 최악의 멤버 찾기

 

flights_sml %>%
group_by(year, month, day) %>%
filter(rank(desc(arr_delay)) < 10)
#> # A tibble: 3,306 x 7
#> # Groups: year, month, day [365]
#> year month day dep_delay arr_delay distance air_time
#> <int> <int> <int> <dbl> <dbl> <dbl> <dbl>
#> 1 2013 1 1 853 851 184 41
#> 2 2013 1 1 290 338 1134 213
#> 3 2013 1 1 260 263 266 46
#> 4 2013 1 1 157 174 213 60
#> 5 2013 1 1 216 222 708 121
#> 6 2013 1 1 255 250 589 115
#> # … with 3,300 more rows

 

  • 임계값보다 큰 모든 그룹 찾기

 

popular_dests <- flights %>%
group_by(dest) %>%
filter(n() > 365)
popular_dests
#> # A tibble: 332,577 x 19
#> # Groups: dest [77]
#> year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
#> <int> <int> <int> <int> <int> <dbl> <int> <int>
#> 1 2013 1 1 517 515 2 830 819
#> 2 2013 1 1 533 529 4 850 830
#> 3 2013 1 1 542 540 2 923 850
#> 4 2013 1 1 544 545 -1 1004 1022
#> 5 2013 1 1 554 600 -6 812 837
#> 6 2013 1 1 554 558 -4 740 728
#> # … with 332,571 more rows, and 11 more variables: arr_delay <dbl>,
#> # carrier <chr>, flight <int>, tailnum <chr>, origin <chr>, dest <chr>,
#> # air_time <dbl>, distance <dbl>, hour <dbl>, minute <dbl>, time_hour <dttm>

 

  • 그룹 메트릭 별로 계산하도록 표준화

 

popular_dests %>%
filter(arr_delay > 0) %>%
mutate(prop_delay = arr_delay / sum(arr_delay)) %>%
select(year:day, dest, arr_delay, prop_delay)
#> # A tibble: 131,106 x 6
#> # Groups: dest [77]
#> year month day dest arr_delay prop_delay
#> <int> <int> <int> <chr> <dbl> <dbl>
#> 1 2013 1 1 IAH 11 0.000111
#> 2 2013 1 1 IAH 20 0.000201
#> 3 2013 1 1 MIA 33 0.000235
#> 4 2013 1 1 ORD 12 0.0000424
#> 5 2013 1 1 FLL 19 0.0000938
#> 6 2013 1 1 ORD 8 0.0000283
#> # … with 131,100 more rows


그룹화된 필터는 그룹화된 mutate 다음에 그룹화되지 않은 필터가 옵니다. 가급적 이러한 방식은 사용하지 않습니다. 조작을 올바르게 수행했는지 확인하기 어렵습니다.

그룹화된 돌연변이 및 필터에서 가장 자연스럽게 작동하는 함수를 창 함수(vs. 요약에 사용되는 요약 함수)라고 합니다. 해당 비네트에서 유용한 창 기능에 대해 자세히 알아볼 수 있습니다: vignette("window-functions").

 

 

 

반응형

댓글