iT邦幫忙

2024 iThome 鐵人賽

DAY 16
0
Python

眾裏尋它:Python表格利器Great Tables系列 第 16

[Day16] - 生成概略趨勢圖(Nanoplot)

  • 分享至 

  • xImage
  •  

今天我們來介紹如何使用GT.fmt_nanoplot()生成概略趨勢圖。

請留意,GT.fmt_nanoplot()尚屬於實驗性質,有可能會遇到許多bug,歡迎回報至GitHub

GT.fmt_nanoplot()

GT.fmt_nanoplot(self, columns=None, rows=None, plot_type='line', plot_height='2em', missing_vals='marker', autoscale=False, reference_line=None, reference_area=None, expand_x=None, expand_y=None, options=None)

GT.fmt_nanoplot()可以生成「"line"」及「"bar"」兩種型態的概略趨勢圖。

三種常見的使用方式,分別為:

  • 情境1:合併多個欄位為str型態。例如:"1 2 3"。
  • 情境2:以Polars的List型態所收集的一連串數字。
  • 情境3:single-value,即每欄中每一行都為單一數字。

情境1:合併多個欄位

假使我們有一個DataFrame,df1

df1 = pl.DataFrame({"a": [1, 2, 3], "b": [4, 5, 6]})
shape: (3, 2)
┌─────┬─────┐
│ a   ┆ b   │
│ --- ┆ --- │
│ i64 ┆ i64 │
╞═════╪═════╡
│ 1   ┆ 4   │
│ 2   ┆ 5   │
│ 3   ┆ 6   │
└─────┴─────┘

假如我們想將「"a"」欄位及「"b"」欄位合併為欄位「"concat "」,中間以空格分隔,這樣一來就可以組成GT.fmt_nanoplot()所期待的第一種輸入型態。

我們可以這麼做:

df1.with_columns(
    pl.col("a")
    .cast(pl.Utf8)
    .add(pl.lit(" "))
    .add(pl.col("b").cast(pl.Utf8))
    .alias("concat")
)
shape: (3, 3)
┌─────┬─────┬────────┐
│ a   ┆ b   ┆ concat │
│ --- ┆ --- ┆ ---    │
│ i64 ┆ i64 ┆ str    │
╞═════╪═════╪════════╡
│ 1   ┆ 4   ┆ 1 4    │
│ 2   ┆ 5   ┆ 2 5    │
│ 3   ┆ 6   ┆ 3 6    │
└─────┴─────┴────────┘

我們需要不斷使用Expr.add()連接,並記得要使用Expr.cast()轉換型態至str。如果只有兩個欄位的話是還好,但是欄位一多就顯得很亂且容易出錯。

此時,我們可以善用pl.concat_str()。例如:

nanoplot_data = pl.concat_str("a", "b", separator=" ")
df1.with_columns(nanoplot_data.alias("concat"))
shape: (3, 3)
┌─────┬─────┬────────┐
│ a   ┆ b   ┆ concat │
│ --- ┆ --- ┆ ---    │
│ i64 ┆ i64 ┆ str    │
╞═════╪═════╪════════╡
│ 1   ┆ 4   ┆ 1 4    │
│ 2   ┆ 5   ┆ 2 5    │
│ 3   ┆ 6   ┆ 3 6    │
└─────┴─────┴────────┘

「"concat"」欄位準備完成後,我們可以藉其生成「"line"」欄位及「"bar"」欄位,再藉由GT.fmt_nanoplot()來產生兩種概略趨勢圖:

(
    GT(
        df1.with_columns(
            nanoplot_data.alias("concat"),
            nanoplot_data.alias("line"),
            nanoplot_data.alias("bar"),
        )
    )
    .fmt_nanoplot("line", plot_type="line")
    .fmt_nanoplot("bar", plot_type="bar")
)

concat columns

情境2:Polars的List型態

假使我們有一個DataFrame,df2

df2 = pl.DataFrame({"list": [1, 2, 3, 4, 5, 6], "group": list("ababab")})
shape: (6, 2)
┌──────┬───────┐
│ list ┆ group │
│ ---  ┆ ---   │
│ i64  ┆ str   │
╞══════╪═══════╡
│ 1    ┆ a     │
│ 2    ┆ b     │
│ 3    ┆ a     │
│ 4    ┆ b     │
│ 5    ┆ a     │
│ 6    ┆ b     │
└──────┴───────┘

假如我們想將「"list"」欄位針對「"group"」欄位來聚合,這樣一來就可以組成GT.fmt_nanoplot()所期待的第二種輸入型態。

我們可以這麼做:

df2.group_by("group").agg("list")
shape: (2, 2)
┌───────┬───────────┐
│ group ┆ list      │
│ ---   ┆ ---       │
│ str   ┆ list[i64] │
╞═══════╪═══════════╡
│ b     ┆ [2, 4, 6] │
│ a     ┆ [1, 3, 5] │
└───────┴───────────┘

利用DataFrame.GroupBy().agg()可以針對「"group"」的各個欄位值來收集「"list"」欄位相對應的數字。

「"list"」欄位準備完成後,我們可以藉其生成「"line"」欄位及「"bar"」欄位,再藉由GT.fmt_nanoplot()來產生兩種概略趨勢圖:

(
    GT(
        df2.group_by("group")
        .agg("list")
        .with_columns(
            pl.col("list").alias("line"), pl.col("list").alias("bar")
        )
    )
    .fmt_nanoplot(
        "line",
        plot_type="line",
        options=nanoplot_options(
            data_point_radius=8,
            data_point_stroke_color="black",
            data_point_stroke_width=2,
            data_point_fill_color="white",
            data_line_type="straight",
            data_line_stroke_color="brown",
            data_line_stroke_width=2,
            data_area_fill_color="orange",
            vertical_guide_stroke_color="green",
        ),
    )
    .fmt_nanoplot(
        "bar",
        plot_type="bar",
        options=nanoplot_options(
            data_bar_stroke_color="gray",
            data_bar_stroke_width=2,
            data_bar_fill_color="orange",
            data_bar_negative_stroke_color="blue",
            data_bar_negative_stroke_width=1,
            data_bar_negative_fill_color="lightblue",
            reference_line_color="pink",
            reference_area_fill_color="bisque",
            vertical_guide_stroke_color="blue",
        ),
    )
)

polars list

這裡我們可以透過nanoplot_options()提供的多種選項來客製化nanoplot。

情境3:single-value

single-value的使用方式非常直觀,下面這個範例取自官方文件:

single_vals_df = pl.DataFrame(
    {
        "i": range(1, 6),
        "lines": [12.44, 6.34, 5.2, -8.2, 9.23],
        "bars": [4.1, 1.3, -5.3, 0, 8.2],
    }
)
(
    GT(single_vals_df, rowname_col="i")
    .fmt_nanoplot(columns="bars", plot_type="bar")
    .fmt_nanoplot(columns="lines", plot_type="line")
)

single value

由於「"lines"」欄位及「"bars"」欄位中的每行都僅有單一數值,所以gt稱這種型態為single-value

不知道大家有沒有注意到,圖上有出現4.10這個數字。這是因為當滑鼠滑過nanoplot時,將會顯示其值,是nanoplot一個有趣的特色喔!

Code

本日程式碼傳送門


上一篇
[Day15] - 依據表格值套用背景顏色
下一篇
[Day17] - 滄海遺珠
系列文
眾裏尋它:Python表格利器Great Tables30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言