사용데이터 : https://2stndard.tistory.com/68
cumsum()과 seq_along()을 사용한 누적합과 누적평균 구하기
누적 합계는 데이터의 시간의 흐름에 따라 계속적으로 합산되는 데이터를 말한다. 따라서 누적 합계는 대부분 시간의 일정한 단위나 시간의 흐름에 따라 발생된 이벤트에 따라 발생되는 데이터의 합계이다. 이 누적 합계는 1954년에 캠브리지 대학에서 제안되었는데 통계적 프로세스 모니터링의 한 방법으로 광범위하게 사용되고 있다.
누적 평균은 지속적으로 발생되는 데이터들의 누적값에 대한 평균을 말한다. 평균을 구하는데에는 데이터의 합계에 대한 데이터의 빈도의 비율을 말하는데 누적 평균에서는 계속적으로 발생되는 누적합계를 지속적으로 증가되는 데이터 빈도로 나누어 산출된다. 이 누적 평균은 누적 이동 평균(Cumulative Moving Average)이라고도 하는데 시계열 예측(Forecasting)이 모델중 하나로 많이 사용되는 모델이다.
R에서 누적 합계와 누적 평균은 cumsum()
과 seq_along()
을 사용하면 쉽게 구할 수 있다.
누적 합계와 누적 평균 산출에는 21년 이후의 코로나19 확진자의 주별 데이터를 사용하는데 다음과 같이 전처리 한다.
library(lubridate)
df_covid19_by_week <- df_covid19 |>
## 한국 데이터와 각 대륙별 데이터만을 필터링
filter(iso_code %in% c('KOR', 'OWID_ASI', 'OWID_EUR', 'OWID_OCE', 'OWID_NAM', 'OWID_SAM', 'OWID_AFR')) |>
## 읽은 데이터의 마지막 데이터에서 100일전 데이터까지 필터링
filter(date >= as.Date('2021-01-01')) |>
## 국가명을 한글로 변환
mutate(location = case_when(
location == 'South Korea' ~ '한국',
location == 'Asia' ~ '아시아',
location == 'Europe' ~ '유럽',
location == 'Oceania' ~ '오세아니아',
location == 'North America' ~ '북미',
location == 'South America' ~ '남미',
location == 'Africa' ~ '아프리카')) |>
## 국가 이름의 순서를 설정
mutate(location = fct_relevel(location, '한국', '아시아', '유럽', '북미', '남미', '아프리카', '오세아니아')) |>
## 날짜로 정렬
arrange(date) |>
group_by(년 = year(date), 주 = week(date), location) |>
summarise(신규확진자수 = sum(new_cases, na.rm = T)) |>
filter(location == '한국') |>
ungroup()
head(df_covid19_by_week, 10)
## # A tibble: 10 x 4
## 년 주 location 신규확진자수
## <dbl> <dbl> <fct> <dbl>
## 1 2021 1 한국 5589
## 2 2021 2 한국 3883
## 3 2021 3 한국 3021
## 4 2021 4 한국 3133
## 5 2021 5 한국 2736
## 6 2021 6 한국 2706
## 7 2021 7 한국 3291
## 8 2021 8 한국 2794
## 9 2021 9 한국 2716
## 10 2021 10 한국 3048
cumsum()을 사용한 누적 합계 산출
cumsum()
은 누적 합계를 구하는데 사용되는 함수이다. cumsum()
을 사용할 때 하나 주의해야 할 것은 누적 합계의 대상이 되는 벡터나 데이터 프레임 열의 순서에 따라 누적 합계가 구해진다는 것이다.
df_covid19_by_week$누적확진자수 <- cumsum(df_covid19_by_week$신규확진자수)
head(df_covid19_by_week, 10)
## # A tibble: 10 x 5
## 년 주 location 신규확진자수 누적확진자수
## <dbl> <dbl> <fct> <dbl> <dbl>
## 1 2021 1 한국 5589 5589
## 2 2021 2 한국 3883 9472
## 3 2021 3 한국 3021 12493
## 4 2021 4 한국 3133 15626
## 5 2021 5 한국 2736 18362
## 6 2021 6 한국 2706 21068
## 7 2021 7 한국 3291 24359
## 8 2021 8 한국 2794 27153
## 9 2021 9 한국 2716 29869
## 10 2021 10 한국 3048 32917
cumsum()
은 R base에서 제공하는 함수이기 떄문에 dplyr
에서 사용하기 위해서는 mutate()
와 함께 사용해야 한다.
df_covid19_by_week |>
mutate(누적확진자수_dplyr = cumsum(신규확진자수))
## # A tibble: 79 x 6
## 년 주 location 신규확진자수 누적확진자수 누적확진자수_dplyr
## <dbl> <dbl> <fct> <dbl> <dbl> <dbl>
## 1 2021 1 한국 5589 5589 5589
## 2 2021 2 한국 3883 9472 9472
## 3 2021 3 한국 3021 12493 12493
## 4 2021 4 한국 3133 15626 15626
## 5 2021 5 한국 2736 18362 18362
## 6 2021 6 한국 2706 21068 21068
## 7 2021 7 한국 3291 24359 24359
## 8 2021 8 한국 2794 27153 27153
## 9 2021 9 한국 2716 29869 29869
## 10 2021 10 한국 3048 32917 32917
## # ... with 69 more rows
cumsum()
을 사용할때 주의해아 하는 것은 반드시 먼저 대상 데이터의 정렬 상태를 반드시 확인해야 한다는 것이다.
앞서 전처리한 코로나 19의 주별 데이터의 경우는 주차수만으로 정렬을 한다면 연도가 무시되어서 21년 1주차 다음에 22년 1주차가 나오게 되어 잘못된 누적 합계가 산출되게 된다.
df_covid19_by_week |>
arrange(주) |>
mutate(누적확진자수_dplyr = cumsum(신규확진자수))
## # A tibble: 79 x 6
## 년 주 location 신규확진자수 누적확진자수 누적확진자수_dplyr
## <dbl> <dbl> <fct> <dbl> <dbl> <dbl>
## 1 2021 1 한국 5589 5589 5589
## 2 2022 1 한국 25762 599246 31351
## 3 2021 2 한국 3883 9472 35234
## 4 2022 2 한국 26969 626215 62203
## 5 2021 3 한국 3021 12493 65224
## 6 2022 3 한국 38290 664505 103514
## 7 2021 4 한국 3133 15626 106647
## 8 2022 4 한국 84848 749353 191495
## 9 2021 5 한국 2736 18362 194231
## 10 2022 5 한국 159896 909249 354127
## # ... with 69 more rows
이를 정상적으로 산출하기 위해서는 주차수와 더불어 연도별로도 정렬이 되어야 하며 연도별로 먼저 정렬되어야 한다.
df_covid19_by_week |>
arrange(년, 주) |>
mutate(누적확진자수_dplyr = cumsum(신규확진자수))
## # A tibble: 79 x 6
## 년 주 location 신규확진자수 누적확진자수 누적확진자수_dplyr
## <dbl> <dbl> <fct> <dbl> <dbl> <dbl>
## 1 2021 1 한국 5589 5589 5589
## 2 2021 2 한국 3883 9472 9472
## 3 2021 3 한국 3021 12493 12493
## 4 2021 4 한국 3133 15626 15626
## 5 2021 5 한국 2736 18362 18362
## 6 2021 6 한국 2706 21068 21068
## 7 2021 7 한국 3291 24359 24359
## 8 2021 8 한국 2794 27153 27153
## 9 2021 9 한국 2716 29869 29869
## 10 2021 10 한국 3048 32917 32917
## # ... with 69 more rows
df_covid19_by_week |>
arrange(년, 주) |>
mutate(누적확진자수_dplyr = cumsum(신규확진자수)) |>
mutate(주 = sprintf('%02d', 주)) |>
ggplot(aes(x = as.factor(paste0(년, '-', 주)), y = 누적확진자수_dplyr)) +
geom_line(aes(group = location)) +
scale_x_discrete(guide = guide_axis(check.overlap = TRUE)) +
theme(axis.text.x = element_text(angle = 90)) +
labs(x = '연월')
cumsum()과 seq_anlong()을 사용한 누적 평균 산출
누적 평균 산출을 위해서는 앞서 산출했던 cumsum()
의 결과를 해당 cumsum()
을 산출하는데 사용한 데이터의 빈도수를 나누어야 한다. 하지만 몇개의 데이터가 합쳐져서 누적 합계가 산출되었는지를 가르키는 변수는 설정되지 않았다. 데이터를 얼핏 보면 ‘주’ 열을 사용하면 될 것같지만 ’연’이 넘어가면 ’주’도 1부터 다시 시작하기 때문에 이를 사용하기에는 어렵다. 그렇다면 열에 해당하는 시퀀스 넘버를 붙여주면 될 것이다. 이를 열로 만들어 놓으면 될수 있지만 이런 경우 사용되는 함수가 seq_along()
이다.
seq_along()
은 일련의 연속된 수치를 생성하는 함수이다. 이렇게 사용하는 함수는 seq()
가 가장 많이 사용되지만 seq()
는 시작값인 from
과 마지막 값인 to
를 설정해 주어야 하는 반면 seq_along()
은 매개변수로 설정된 벡터의 길이만큼 연속된 수치가 설정된다. 결국 seq_along(x)
는 seq(from = 1, to = length(x))
와 동일한 결과를 낸다.
df_covid19_by_week$누적확진자수_평균 <- cumsum(df_covid19_by_week$신규확진자수)/seq_along(df_covid19_by_week$신규확진자수)
head(df_covid19_by_week, 10)
## # A tibble: 10 x 6
## 년 주 location 신규확진자수 누적확진자수 누적확진자수_평균
## <dbl> <dbl> <fct> <dbl> <dbl> <dbl>
## 1 2021 1 한국 5589 5589 5589
## 2 2021 2 한국 3883 9472 4736
## 3 2021 3 한국 3021 12493 4164.
## 4 2021 4 한국 3133 15626 3906.
## 5 2021 5 한국 2736 18362 3672.
## 6 2021 6 한국 2706 21068 3511.
## 7 2021 7 한국 3291 24359 3480.
## 8 2021 8 한국 2794 27153 3394.
## 9 2021 9 한국 2716 29869 3319.
## 10 2021 10 한국 3048 32917 3292.
df_covid19_by_week |>
arrange(년, 주) |>
mutate(누적평균 = cumsum(신규확진자수)/seq_along(신규확진자수))
## # A tibble: 79 x 7
## 년 주 location 신규확진자수 누적확진자수 누적확진자수_평균 누적평균
## <dbl> <dbl> <fct> <dbl> <dbl> <dbl> <dbl>
## 1 2021 1 한국 5589 5589 5589 5589
## 2 2021 2 한국 3883 9472 4736 4736
## 3 2021 3 한국 3021 12493 4164. 4164.
## 4 2021 4 한국 3133 15626 3906. 3906.
## 5 2021 5 한국 2736 18362 3672. 3672.
## 6 2021 6 한국 2706 21068 3511. 3511.
## 7 2021 7 한국 3291 24359 3480. 3480.
## 8 2021 8 한국 2794 27153 3394. 3394.
## 9 2021 9 한국 2716 29869 3319. 3319.
## 10 2021 10 한국 3048 32917 3292. 3292.
## # ... with 69 more rows
df_covid19_by_week |>
arrange(년, 주) |>
mutate(누적평균 = cumsum(신규확진자수)/seq_along(신규확진자수)) |>
mutate(주 = sprintf('%02d', 주)) |>
ggplot(aes(x = as.factor(paste0(년, '-', 주)), y = 누적평균)) +
geom_line(aes(group = location)) +
scale_x_discrete(guide = guide_axis(check.overlap = TRUE)) +
theme(axis.text.x = element_text(angle = 90)) +
labs(x = '연월')
'데이터 전처리' 카테고리의 다른 글
연도별 시도별 비정규 교원 1인당 학생수 in R - rank() (20) | 2022.07.13 |
---|---|
행정구역별 연령별 학생 비율 구하기 in R - mutate_all, mutate_at, mutate_if (0) | 2022.07.13 |
열 이름 바꾸기 in R (0) | 2022.06.21 |
일별(일간) 데이터를 주별(주간) 데이터로 만들기 in R (0) | 2022.06.18 |
일별 데이터를 월별 데이터로 만들기 (0) | 2022.06.16 |
댓글