iBetter Books
수정

데이터 시각화 연동 (matplotlib·plotly·altair)

SQL 결과와 데이터프레임을 손에 넣었습니다. 이제 시각화 차례입니다.

이 챕터는 matplotlib, plotly, altair를 각각 처음부터 가르치는 자리가 아닙니다. 시각화 라이브러리 자체는 별도로 다루는 교재에 맡기고, 여기서는 한 가지에만 집중합니다. marimo 안에서 차트 객체를 어떻게 렌더링하고, SQL·위젯과 어떻게 반응형으로 연결하는가입니다.

marimo에서 차트를 표시하는 방법

marimo에서 차트를 표시하는 방법은 단순합니다. 차트 객체(또는 Figure 객체)를 셀의 마지막 표현식으로 놓으면 됩니다.

import marimo as moimport matplotlib.pyplot as pltimport pandas as pddata = pd.DataFrame({    "month": ["1월", "2월", "3월", "4월", "5월"],    "sales": [120, 95, 160, 140, 180],})fig, ax = plt.subplots()ax.bar(data["month"], data["sales"])ax.set_title("월별 매출")ax.set_ylabel("매출 (만원)")fig

fig 객체를 셀 마지막에 두면 marimo가 이를 렌더링합니다. matplotlib의 경우 Figure 객체를 마지막에 놓는 것이 핵심입니다. plt.show()를 부를 필요가 없습니다.

plotly도 같은 방식입니다.

import marimo as moimport plotly.express as pximport pandas as pddata = pd.DataFrame({    "category": ["A", "B", "C", "D"],    "value": [30, 50, 20, 40],})fig = px.bar(data, x="category", y="value", title="카테고리별 비교")fig

altair도 마찬가지입니다.

import marimo as moimport altair as altimport pandas as pddata = pd.DataFrame({    "x": [1, 2, 3, 4, 5],    "y": [2, 4, 3, 5, 4],})chart = alt.Chart(data).mark_line().encode(    x="x:Q",    y="y:Q",).properties(title="라인 차트")chart

SQL 결과를 바로 차트로 시각화

mo.sql() 결과는 데이터프레임입니다. 이를 바로 차트에 넘기면 됩니다.

import marimo as mo# 셀 1 — SQL로 집계monthly_sales = mo.sql(f"""    SELECT        strftime(date, '%Y-%m') AS month,        SUM(amount) AS total    FROM 'data/sales.csv'    GROUP BY month    ORDER BY month""")monthly_sales
import marimo as moimport plotly.express as px# 셀 2 — SQL 결과를 바로 plotly에 전달fig = px.line(    monthly_sales,    x="month",    y="total",    title="월별 매출 추이",    labels={"month": "월", "total": "총 매출"},)fig

monthly_sales가 Pandas DataFrame이라면 plotly는 그냥 그걸 씁니다. Polars DataFrame이라면 최신 plotly는 Polars도 직접 받습니다. 환경에 따라 다를 수 있으므로, 확실히 하려면 monthly_sales.to_pandas()로 변환하는 방법도 있습니다.

위젯과 연결해 반응형 차트 만들기

위젯과 차트를 연결하면 필터를 바꿀 때마다 차트가 자동으로 갱신됩니다.

import marimo as mo# 셀 1 — 연도 선택year = mo.ui.dropdown(    ["2022", "2023", "2024"],    value="2024",    label="연도",)year
import marimo as mo# 셀 2 — 선택된 연도의 데이터 조회region_data = mo.sql(f"""    SELECT region, SUM(amount) AS total    FROM 'data/sales.csv'    WHERE strftime(date, '%Y') = '{year.value}'    GROUP BY region    ORDER BY total DESC""")region_data
import marimo as moimport plotly.express as px# 셀 3 — 결과를 차트로fig = px.bar(    region_data,    x="region",    y="total",    title=f"{year.value}년 지역별 매출",)fig

year 드롭다운을 바꾸면 DAG가 셀 2와 셀 3을 순서대로 재실행합니다. SQL 쿼리가 새 연도로 실행되고, 차트가 새 데이터로 그려집니다. 세 셀이 하나의 반응형 파이프라인입니다.

matplotlib의 상태 관리 주의사항

matplotlib는 전역 상태를 유지하는 방식으로 동작합니다. 셀이 재실행될 때마다 Figure를 새로 만들지 않으면, 이전 실행의 상태가 누적될 수 있습니다.

import marimo as moimport matplotlib.pyplot as plt# 재실행될 때 이전 Figure 닫기plt.close("all")fig, ax = plt.subplots(figsize=(8, 4))ax.plot([1, 2, 3, 4], [10, 20, 15, 25])ax.set_title("샘플 라인 차트")fig

또는 with plt.style.context(...) 패턴이나 Figure 객체를 명시적으로 생성하고 닫는 방식을 사용합니다. 셀이 재실행될 때마다 Figure를 새로 만드는 습관을 들이면 예상치 못한 렌더링 문제를 피할 수 있습니다.

plotly와 altair는 함수형 API 방식이라 이 문제가 발생하지 않습니다.

여러 차트를 함께 표시하기

여러 차트를 한 셀에 나란히 또는 위아래로 배치하려면 mo.hstack()mo.vstack()을 씁니다.

import marimo as moimport plotly.express as pximport pandas as pddata = pd.DataFrame({    "category": ["A", "B", "C"],    "value1": [30, 50, 20],    "value2": [15, 40, 35],})fig1 = px.bar(data, x="category", y="value1", title="지표 1")fig2 = px.bar(data, x="category", y="value2", title="지표 2")mo.hstack([fig1, fig2])

mo.hstack()에 차트 객체를 리스트로 넣으면 가로로 나란히 표시됩니다.

정리

  • marimo에서 차트 객체를 셀 마지막 표현식으로 놓으면 렌더링됩니다. matplotlib는 Figure 객체를, plotly와 altair는 Figure/Chart 객체를 마지막에 씁니다.
  • mo.sql() 결과 데이터프레임을 바로 차트 함수에 넘겨 시각화할 수 있습니다.
  • 위젯 값을 SQL에 삽입하고, SQL 결과로 차트를 그리면 위젯 조작만으로 차트가 갱신되는 반응형 파이프라인이 됩니다.
  • matplotlib는 전역 상태를 가지므로 셀 재실행 시 Figure를 새로 만들거나 이전 Figure를 닫는 습관을 들입니다.
  • 여러 차트를 나란히 배치할 때는 mo.hstack()mo.vstack()을 씁니다.