R

ReflexKR

Reflex公式ドキュメント

コンポーネント工房:Reflexライブラリ100

·

講座の概要

レイアウト

·

Box

·

Flex

·

Stack

·

Grid

·

Container

·

Section

·

Center

·

Spacer

·

Separator

·

Card

·

Inset

·

Aspect Ratio

·

Fragment

タイポグラフィ

·

Text

·

Heading

·

Link

·

Code

·

Markdown

·

Blockquote

·

Quote

·

Strong

·

Em

·

Kbd

フォーム

·

Button

·

Input

·

Text Area

·

Checkbox

·

Switch

·

Radio Group

·

Select

·

Slider

·

Form

·

Upload

データ表示

·

Badge

·

Avatar

·

Icon

·

Callout

·

List

·

Data List

·

Code Block

·

Progress

·

Spinner

·

Scroll Area

·

Moment

開閉と切り替え

·

Tabs

·

Accordion

·

Segmented Control

オーバーレイ

·

Tooltip

·

Popover

·

Hover Card

·

Dialog

·

Alert Dialog

·

Drawer

·

Dropdown Menu

·

Context Menu

·

Toast

動的レンダリング

·

Cond

·

Match

·

Foreach

·

Auto Scroll

メディア

·

Image

·

Audio

·

Video

表とデータグリッド

·

Table

·

Data Table

·

Data Editor

チャート

·

Area Chart

·

Bar Chart

·

Line Chart

·

Composed Chart

·

Pie Chart

·

Radar Chart

·

Radial Bar Chart

·

Scatter Chart

·

Funnel Chart

·

Treemap

·

Sankey Chart

·

Error Bar

チャートの部品

·

Axis

·

Cartesian Grid

·

Chart Tooltip

·

Legend

·

Label

·

Reference

·

Brush

ほかのチャートライブラリ

·

Plotly

·

Pyplot

HTML要素

·

HTML

·

HTML Text

·

HTML Layout

·

HTML Forms

·

HTML Media

·

HTML Tables

·

SVG

そのほかの道具

·

Theme

·

Skeleton

·

Clipboard

·

Html Embed

·

Script

·

Memo

コンポーネント工房:Reflexライブラリ100
チャート

Sankey Chart

rx.recharts.sankey_chartrx.recharts.sankey_chart.noderx.recharts.sankey_chart.link

公式ドキュメント

工房の注文書

1か月の収入がどこから入り、家賃・食費・貯金にいくらずつ流れていくのかを、流れの太さで見せてください。

rx.recharts.sankey_chartは、ノード(節点)とその間を流れる量を帯の太さで見せるサンキー図です。訪問者がどのページを経由して購入まで進むのか、お金がどこから来てどこへ行くのか、といった「流れ」を見たいときに使います。

dataはリストではなく、{"nodes": [...], "links": [...]}という形のdictです。linksのsourceとtargetはnodesリストの番号(0始まり)で、valueがその流れの量です。ツールチップは子として入れます。

sankeychart_data = {
    "nodes": [
        {"name": "Website"},
        {"name": "Landing"},
        {"name": "Product"},
        {"name": "Checkout"},
        {"name": "Purchase"},
    ],
    "links": [
        {"source": 0, "target": 1, "value": 1200},
        {"source": 1, "target": 2, "value": 900},
        {"source": 2, "target": 3, "value": 420},
        {"source": 3, "target": 4, "value": 260},
    ],
}


rx.recharts.sankey_chart(
    rx.recharts.graphing_tooltip(),
    data=sankeychart_data,
    node_padding=24,
    node_width=12,
    link_curvature=0.55,
    width="100%",
    height=300,
)

プロパティを変えてみる

nodeとlinkにdictを渡すと、すべてのノードと帯に同じSVGスタイルが適用されます。dictのキーはSVG属性名そのまま(strokeOpacityのようなキャメルケース)で書きます。link_curvatureは帯の曲がり具合(0なら直線)です。

プロパティを変えてみる

node_color

link_opacity

0.35

link_curvature

0.5

sort

rx.recharts.sankey_chart(
    rx.recharts.graphing_tooltip(),
    data={
        "nodes": [{"name": "Ads"}, {"name": "Search"}, {"name": "Signup"}, {"name": "Leave"}, {"name": "Paid"}],
        "links": [
            {"source": 0, "target": 2, "value": 300},
            {"source": 0, "target": 3, "value": 500},
            {"source": 1, "target": 2, "value": 600},
            {"source": 1, "target": 3, "value": 200},
            {"source": 2, "target": 4, "value": 350},
        ],
    },
    node={"fill": rx.color("indigo", 9), "stroke": "none"},
    link={"stroke": rx.color("gray", 9), "strokeOpacity": 0.35},
    link_curvature=0.5,
    sort=True,
    node_padding=20,
    node_width=12,
    width="100%",
    height=300,
)
sortをオフにするとノードがデータに書かれた順に並び、オンにすると帯が絡みにくくなるよう上下の順番を決めます。
プロパティ値既定値用途
data{"nodes": [...], "links": [...]}なしノードと流れ。リンクはノードの番号で結ぶ
name_key文字列"name"ノード名のキー
data_key文字列"value"流れの量のキー
nodedict または @sankey_chart.node 関数ノードのスタイル、または自分で描く関数
linkdict または @sankey_chart.link 関数帯のスタイル、または自分で描く関数
node_width数値10ノードの棒の太さ
node_padding数値10同じ列のノードどうしの間隔
link_curvature0〜10.5帯の曲がり具合
sortTrue / FalseTrueノードを上下に並べ替えるかどうか
iterations数値32配置計算を繰り返す回数
margin, width, heightdict / 数値・パーセント各5 / "100%"余白とサイズ。右側の名前が切れるならmarginを広げる
イベントon_click on_mouse_enter on_mouse_leave on_mouse_moveチャート領域のマウスイベント

Stateで変わる流れ

dataにStateのdictをつなぎました。ボタンを押すとリンクのvalueが新しく決まり、帯の太さとノードの高さが計算し直されます。ここではnodeとlinkにdictで色・枠線・透明度を指定しています。

import random
from typing import Any


class SankeyChartLiveState(rx.State):
    data: dict[str, Any] = {
        "nodes": [
            {"name": "Marketing"},
            {"name": "Trial"},
            {"name": "Sales"},
            {"name": "Support"},
            {"name": "Retained"},
        ],
        "links": [
            {"source": 0, "target": 1, "value": 600},
            {"source": 1, "target": 2, "value": 320},
            {"source": 2, "target": 4, "value": 210},
            {"source": 1, "target": 3, "value": 180},
            {"source": 3, "target": 4, "value": 130},
        ],
    }

    @rx.event
    def shuffle(self):
        self.data = {
            "nodes": self.data["nodes"],
            "links": [{**link, "value": random.randint(80, 700)} for link in self.data["links"]],
        }


rx.vstack(
    rx.recharts.sankey_chart(
        rx.recharts.graphing_tooltip(),
        data=SankeyChartLiveState.data,
        node={
            "fill": rx.color("accent", 7),
            "stroke": rx.color("accent", 10),
            "strokeWidth": 2,
        },
        link={
            "stroke": rx.color("gray", 7),
            "strokeOpacity": 0.35,
        },
        node_padding=18,
        node_width=14,
        width="100%",
        height=300,
    ),
    rx.button("Randomize flows", on_click=SankeyChartLiveState.shuffle),
    width="100%",
)

ノードと帯を自分で描く

dictで足りなければ、ノードと帯を描く関数を自分で書きます。@rx.recharts.sankey_chart.nodeを付けた関数は、ノード1つの情報(SankeyNodeProps:位置x・y、大きさwidth・height、元のデータpayload)をVarとして受け取り、SVGコンポーネントを返します。@rx.recharts.sankey_chart.linkは帯1本の情報(SankeyLinkProps:始点・終点の座標、太さlinkWidth、payload)を受け取ります。

  • rx.recharts.use_chart_width()はチャートの実際の幅です。右端のノードで名前を左側に置くのに使います。
  • データに入れた独自のキー("fill")は、payload.to(dict)["fill"]のようにdictに変換して読みます。
  • rx.vars.use_id()は帯ごとに重ならないグラデーションのidを作ります。帯は出発ノードの色から到着ノードの色へと染まります。

2つの関数は、画面で使う前にモジュールレベルで一度だけ定義します。

sankeychart_styled = {
    "nodes": [
        {"name": "Sources", "fill": rx.color("blue", 8)},
        {"name": "Direct", "fill": rx.color("green", 8)},
        {"name": "Search", "fill": rx.color("grass", 8)},
        {"name": "Paid", "fill": rx.color("amber", 8)},
        {"name": "Revenue", "fill": rx.color("purple", 8)},
    ],
    "links": [
        {"source": 0, "target": 1, "value": 350},
        {"source": 0, "target": 2, "value": 500},
        {"source": 0, "target": 3, "value": 220},
        {"source": 1, "target": 4, "value": 190},
        {"source": 2, "target": 4, "value": 260},
        {"source": 3, "target": 4, "value": 150},
    ],
}


@rx.recharts.sankey_chart.node
def sankeychart_node(node: rx.Var[rx.recharts.SankeyNodeProps]) -> rx.Component:
    # put the name on the left for the rightmost nodes
    is_out = node.x + node.width + 6 > rx.recharts.use_chart_width()
    return rx.fragment(
        rx.el.svg.text(
            node.payload.name,
            x=rx.cond(is_out, node.x - 6, node.x + node.width + 6).to(int),
            y=(node.y + node.height / 2).to(int),
            text_anchor=rx.cond(is_out, "end", "start"),
            fill=rx.color("gray", 12),
            font_size=10,
        ),
        rx.el.svg.rect(
            x=node.x.to(int),
            y=node.y.to(int),
            width=node.width.to(int),
            height=node.height.to(int),
            # read the payload's custom key (fill) after converting it to a dict
            fill=node.payload.to(dict)["fill"],
            stroke=rx.color("gray", 12),
            stroke_width=1,
        ),
    )


@rx.recharts.sankey_chart.link
def sankeychart_link(link: rx.Var[rx.recharts.SankeyLinkProps]) -> rx.Component:
    link_id = rx.vars.use_id()
    source = link.payload.source.to(dict)
    target = link.payload.target.to(dict)
    return rx.fragment(
        rx.el.svg.linear_gradient(
            rx.el.svg.stop(offset="0%", stop_color=source["fill"]),
            rx.el.svg.stop(offset="100%", stop_color=target["fill"]),
            id=link_id,
        ),
        rx.el.svg.path(
            d=(
                f"M{link.sourceX},{link.sourceY} "
                f"C{link.sourceControlX},{link.sourceY} "
                f"{link.targetControlX},{link.targetY} "
                f"{link.targetX},{link.targetY}"
            ),
            fill="none",
            stroke=f"url(#{link_id})",
            stroke_opacity=0.35,
            stroke_width=link.linkWidth,
        ),
        rx.el.svg.text(
            link.payload.value,
            x=((link.sourceX + link.targetX) / 2).to(int),
            y=((link.sourceY + link.targetY) / 2).to(int),
            text_anchor="middle",
            fill=rx.color("gray", 12),
            font_size=10,
        ),
    )


rx.recharts.sankey_chart(
    data=sankeychart_styled,
    node=sankeychart_node,
    link=sankeychart_link,
    width="100%",
    height=320,
)

注文書を仕上げる

2つの収入源が「Budget」ノードに集まり、3つに分かれます。ノードは濃い色、帯は同じ色の淡い段階で塗って、流れがノードから続いて出ていくように見せ、右のmarginを広げて最後の列の名前が切れないようにしました。

rx.recharts.sankey_chart(
    rx.recharts.graphing_tooltip(),
    data={
        "nodes": [
            {"name": "Salary"},
            {"name": "Side job"},
            {"name": "Budget"},
            {"name": "Rent"},
            {"name": "Food"},
            {"name": "Savings"},
        ],
        "links": [
            {"source": 0, "target": 2, "value": 3000},
            {"source": 1, "target": 2, "value": 600},
            {"source": 2, "target": 3, "value": 1400},
            {"source": 2, "target": 4, "value": 900},
            {"source": 2, "target": 5, "value": 1300},
        ],
    },
    node={"fill": rx.color("accent", 9), "stroke": "none"},
    link={"stroke": rx.color("accent", 6), "strokeOpacity": 0.5},
    node_padding=28,
    node_width=10,
    margin={"top": 10, "right": 80, "bottom": 10, "left": 10},
    width="100%",
    height=300,
)

工房ノート

  • dataは{"nodes": [...], "links": [...]}。リンクのsource・targetはノードの番号。

  • node・linkにdictを渡すと全体のスタイルになる(SVG属性名はキャメルケース)。

  • node_width・node_padding・link_curvature・sortで配置を整える。

  • もっと自由に描くなら、@rx.recharts.sankey_chart.node / .link関数でSVGを返す。

  • dataにStateのdictをつなぐと、流れが変わったときに計算し直される。

← 前へ

チャート · Treemap

次へ →

チャート · Error Bar

新しい授業・講座のお知らせを受け取る

この講座に授業が追加されたり、続きの講座が公開されたりしたらメールでお知らせします。

収集項目:メールアドレス・目的:この講座の新しい授業・公開のお知らせ・保有期間:解除のご依頼まで。他の目的には使わず、第三者にも提供しません。お知らせメールに返信いただければすぐに削除します。

質問と回答

この回について気になることを書き込んでください。すべての言語のページの質問がここに集まります。

リンクや書式なしで、そのままの文字で表示されます。

R

ReflexKR

触って学ぶPythonとReflex。すべての例はReflex 0.10.0で実際に動かして確認しています。

ReflexKRはバナー広告なし・無料で運営しています。役に立ったら、コーヒー一杯で応援してください。 ☕ コーヒーで応援する

アフィリエイトと支援について
한국어English日本語简体中文EspañolDeutsch

© 2026 ReflexKR · Since 2026 · CC BY-NC 4.0

Built with Reflex