본문 바로가기
  • plotly로 바로쓰는 동적시각화 in R & 파이썬
Plotly in R - 그래프에 마우스를 올려봅시다

퍼넬(깔때기, Funnel) 차트 in R

by 아참형인간 2022. 4. 26.
funnel.knit

사용데이터 : https://2stndard.tistory.com/68

피라미드를 그려보자 - 퍼널 차트

피라미드 그래프는 보통 인구 연령별 인구수를 표현하는 그래프에서 많이 사용된다. 하지만 plotly에서는 피라미드 그래프라는 이름으로 사용되지 않고 퍼널(깔때기, funnel) trace라는 이름으로 사용된다. 퍼널 trace는 변량의 크기를 길이로 표현한 막대로 표현하고 각 막대의 중간을 맞춰 양쪽으로 퍼져나가는 깔때기 형태의 trace이다. 이 퍼널 차트는 영업 및 마케팅 부서에서 자주 사용되는데 여러 단계별로 값이나 지표가 변화하는 것을 한 눈에 표현하기 위한 목적으로 사용한다.

코로나19 데이터를 사용하여 퍼널 차트를 만들기 위해 일간 코로나19 데이터를 주(week) 단위로 요약하여 주 단위로 값의 변화를 살펴보겠다. 먼저 최근 100일간의 우리나라 코로나19 신규 확진자 데이터를 주 단위로 요약하는 전처리는 다음과 같다.

df_funnel <- 
  df_covid19_100 |> 
  filter(iso_code == 'KOR') |>
  ## date의 월 단위 열을 yearmonth에 저장
  mutate(date_by_week = lubridate::floor_date(date, "week"), 
         yearweekth =  paste0(lubridate::year(date_by_week), '년 ', 
                           lubridate::week(date_by_week), '주')) |> 
  ## iso_code, yearmonth로 그룹화
  group_by(iso_code, date_by_week, yearweekth) |>
  ## new_cases 합계 산출
  summarise(new_cases = sum(new_cases))

전처리된 데이터를 사용하여 퍼널 차트를 그려본다. X축은 데이터 값인 신규 확진자 수를 매핑하고 Y축은 단계로 구분했던 연도의 주(Week) 차수를 매핑함으로서 퍼널 차트를 쉽게 그릴 수 있다.

df_funnel |>
  plot_ly() |>
  add_trace(type = 'funnel', x = ~new_cases, y = ~date_by_week, 
            text = ~new_cases, texttemplate = '%{text:,.0f}') |>
  layout(title = '우리나라 주별 확진자수', 
    yaxis = list(title = '', 
                      tickvals = ~date_by_week, 
                      ticktext = ~yearweekth), 
    margin = margins)

앞선 퍼널 차트에서 보면 우리나라의 신규 확진자 수는 2022년 4주차부터 늘어나기 시작해서 2022년 11주차(3.13~3.19)까지 급격히 증가하고 감소하는 상황이라는 것이 한눈에 보인다.

만약 이 퍼널 차트를 전체 대륙이 한꺼번에 나타나도록 그리기 위해서는 어떻게 해야할까? 여러 변량을 추가하려면 add_trace()를 추가하면 간단히 그려진다. 다음은 아시아와 유럽의 신규 확진자 주별 데이터에 대한 퍼널 차트이다.

df_funnel_Asia <- 
  df_covid19_100 |> 
  filter(location == '아시아') |>
  ## date의 월 단위 열을 yearmonth에 저장
  mutate(date_by_week = lubridate::floor_date(date, "week"), 
         yearweekth =  paste0(lubridate::year(date_by_week), '년 ', 
                           lubridate::week(date_by_week), '주')) |> 
  ## iso_code, yearmonth로 그룹화
  group_by(iso_code, date_by_week, yearweekth) |>
  ## new_cases 합계 산출
  summarise(new_cases = sum(new_cases))

df_funnel_Europe <- 
  df_covid19_100 |> 
  filter(location == '유럽') |>
  ## date의 월 단위 열을 yearmonth에 저장
  mutate(date_by_week = lubridate::floor_date(date, "week"), 
         yearweekth =  paste0(lubridate::year(date_by_week), '년 ', 
                           lubridate::week(date_by_week), '주')) |> 
  ## iso_code, yearmonth로 그룹화
  group_by(iso_code, date_by_week, yearweekth) |>
  ## new_cases 합계 산출
  summarise(new_cases = sum(new_cases))

df_funnel_Asia |> 
  plot_ly() |>
  add_trace(type = 'funnel', name = '아시아', 
            x = ~new_cases, y = ~date_by_week, 
            text = ~new_cases, texttemplate = '%{text:,.0f}') |>
  add_trace(data = df_funnel_Europe,type = 'funnel', name = '유럽',
            x = ~new_cases, y = ~date_by_week, 
            text = ~new_cases, texttemplate = '%{text:,.0f}') |>
  layout(title = '아시아와 유럽의 주별 확진자수', 
    yaxis = list(title = '', 
                      tickvals = ~date_by_week, 
                      ticktext = ~yearweekth), 
    margin = margins)

댓글