iBetter Books
수정

애니메이션

지윤은 TED에서 한 번 본 영상을 기억했습니다. 한스 로슬링이라는 통계학자가 수백 개의 나라를 버블로 표현하고, 연도가 바뀌면서 버블들이 살아있는 것처럼 움직이는 차트. 그걸 보고 "데이터도 이렇게 살아있을 수 있구나"라고 느꼈습니다.

Plotly Express로 같은 걸 만들 수 있다는 사실을 알았을 때, 지윤은 바로 노트북을 열었습니다.

animation_frame 파라미터

animation_frame은 어떤 열(column)을 시간 축으로 쓸지 지정합니다. 그 열의 값이 하나씩 바뀌면서 프레임이 바뀝니다.

# 새 파일: animation_basic.pyimport plotly.express as px# gapminder 데이터: 국가별 GDP, 기대수명, 인구 시계열df = px.data.gapminder()fig = px.scatter(    df,    x="gdpPercap",    y="lifeExp",    animation_frame="year",        # 연도가 프레임    animation_group="country",     # 국가가 그룹 (연결 추적)    size="pop",                    # 인구가 버블 크기    color="continent",             # 대륙이 색상    hover_name="country",          # 마우스 오버시 국가명    log_x=True,                    # X축 로그 스케일    range_x=[100, 100000],         # X축 범위 고정    range_y=[25, 90],              # Y축 범위 고정    title="GDP vs 기대수명 변화 (1952~2007)")fig.show()

실행 결과

실행하면 화면 아래에 재생 버튼과 연도 슬라이더가 나타납니다. 재생 버튼을 누르면 1952년부터 2007년까지 나라들이 움직입니다.

animation_group의 역할

animation_group은 프레임이 바뀔 때 같은 요소를 추적하게 합니다. 예를 들어 "한국"이라는 버블이 1952년에서 1957년으로 넘어갈 때 자연스럽게 이동하는 애니메이션을 만들어줍니다. animation_group이 없으면 버블이 사라졌다가 새로 나타나는 것처럼 보입니다.

축 고정의 중요성

range_xrange_y로 축 범위를 고정하지 않으면, 프레임마다 축 범위가 바뀝니다. 값이 증가하는데 차트 크기가 줄어드는 것처럼 보여서 데이터를 오해할 수 있습니다. 애니메이션을 만들 때는 반드시 축 범위를 고정하는 것이 좋습니다.

# 잘못된 예: 축이 고정되지 않아 비교가 어려움fig_bad = px.scatter(df, x="gdpPercap", y="lifeExp", animation_frame="year")# 올바른 예: 축 고정fig_good = px.scatter(    df,    x="gdpPercap",    y="lifeExp",    animation_frame="year",    range_x=[100, 100000],    range_y=[25, 90],    log_x=True)

재생 속도와 버튼 설정

animation_frame으로 만든 애니메이션의 재생 속도와 UI를 조절할 수 있습니다.

# 새 파일: animation_settings.pyimport plotly.express as pxdf = px.data.gapminder()fig = px.scatter(    df,    x="gdpPercap",    y="lifeExp",    animation_frame="year",    animation_group="country",    size="pop",    color="continent",    hover_name="country",    log_x=True,    range_x=[100, 100000],    range_y=[25, 90],    title="재생 속도 조절 예시")# 애니메이션 속도 설정 (ms 단위)fig.layout.updatemenus[0].buttons[0].args[1]["frame"]["duration"] = 800fig.layout.updatemenus[0].buttons[0].args[1]["transition"]["duration"] = 300fig.show()

실행 결과

duration=800은 프레임 하나가 0.8초 동안 표시된다는 뜻입니다. 값을 줄이면 빨라집니다.

실전: 연도별 GDP vs 기대수명 (Hans Rosling 스타일)

지윤이 처음 감동받았던 그 차트를 직접 만들어봅니다. 학교 브랜드 템플릿을 적용해서 발표 스타일에 맞게 꾸밉니다.

# 새 파일: gapminder_animation.pyimport plotly.express as pximport plotly.io as pio# 학교 템플릿이 이미 등록되어 있다면 아래 줄 활성화# pio.templates.default = "school"df = px.data.gapminder()fig = px.scatter(    df,    x="gdpPercap",    y="lifeExp",    animation_frame="year",    animation_group="country",    size="pop",    color="continent",    hover_name="country",    hover_data={"pop": ":,", "gdpPercap": ":,.0f"},    log_x=True,    size_max=55,    range_x=[200, 120000],    range_y=[25, 90],    color_discrete_sequence=px.colors.qualitative.D3,    labels={        "gdpPercap": "1인당 GDP (달러, 로그 스케일)",        "lifeExp": "기대수명 (세)",        "pop": "인구",        "continent": "대륙"    },    title="전 세계 GDP와 기대수명의 변화 (1952~2007)")fig.update_layout(    height=600,    title_font_size=18)fig.show()

실행 결과

실행하면 1952년 상태에서 시작합니다. 재생 버튼을 누르면 수십 년의 역사가 수십 초로 압축되어 눈앞에 펼쳐집니다. 아시아 국가들이 오른쪽 위로 빠르게 이동하고, 일부 아프리카 국가들은 1990년대에 잠시 멈추는 모습도 보입니다.

"데이터가 이야기를 한다는 게 이런 거구나."

지윤은 슬라이드에 이 차트를 넣기로 했습니다. 물론 인터랙티브 HTML 파일로 저장해서.