iT邦幫忙

2024 iThome 鐵人賽

DAY 13
0

今天我們來說明,如何使用GT.fmt_unit()搭配define_units(),在表格中任意component格式化各種單位。

GT.fmt_unit()

GT.fmt_units(self, columns=None, rows=None, pattern='{x}')

GT.fmt_unit()可以讓我們格式化各種單位。

其原理是我們可以透過一些預先定義的語法(以下簡稱為「"約定語法"」),來代表如上下標、溫度甚至化學單位。針對化學單位的部份,建議大家可以參考Richard所寫的部落格文章,裡面有一個完整的範例可以參考。

今天我會針對個人最常使用的上標與下標,以下面這個df DataFrame為例來說明:

import polars as pl
from great_tables import GT, html, define_units


df = (
    pl.DataFrame({"x": pl.arange(1, 6, eager=True)})
    .with_columns(
        a2=pl.col("x").add(10), a1=pl.col("x").add(20), a0=pl.col("x").add(30)
    )
    .with_columns(
        y=(
            pl.col("a2").mul(pl.col("x").pow(2))
            + pl.col("a1").mul(pl.col("x"))
            + pl.col("a0")
        )
    )
)
shape: (5, 5)
┌─────┬─────┬─────┬─────┬─────┐
│ x   ┆ a2  ┆ a1  ┆ a0  ┆ y   │
│ --- ┆ --- ┆ --- ┆ --- ┆ --- │
│ i64 ┆ i64 ┆ i64 ┆ i64 ┆ i64 │
╞═════╪═════╪═════╪═════╪═════╡
│ 1   ┆ 11  ┆ 21  ┆ 31  ┆ 63  │
│ 2   ┆ 12  ┆ 22  ┆ 32  ┆ 124 │
│ 3   ┆ 13  ┆ 23  ┆ 33  ┆ 219 │
│ 4   ┆ 14  ┆ 24  ┆ 34  ┆ 354 │
│ 5   ┆ 15  ┆ 25  ┆ 35  ┆ 535 │
└─────┴─────┴─────┴─────┴─────┘

欄位操作

我們可以使用GT.fmt_unit()對整欄進行格式化。

舉例來說,我們可以建立一個「"sup"」欄位及一個「"sub"」欄位:

(
    df.select(
        "x",
        sup=pl.col("x").cast(pl.Utf8).add("^sup"),
        sub=pl.col("x").cast(pl.Utf8).add("_sub"),
    )
)
shape: (5, 3)
┌─────┬───────┬───────┐
│ x   ┆ sup   ┆ sub   │
│ --- ┆ ---   ┆ ---   │
│ i64 ┆ str   ┆ str   │
╞═════╪═══════╪═══════╡
│ 1   ┆ 1^sup ┆ 1_sub │
│ 2   ┆ 2^sup ┆ 2_sub │
│ 3   ┆ 3^sup ┆ 3_sub │
│ 4   ┆ 4^sup ┆ 4_sub │
│ 5   ┆ 5^sup ┆ 5_sub │
└─────┴───────┴───────┘

「"sup"」欄位是由「"x"」欄位轉換為pl.Utf8格式後再加上^sup所組成;而「"sub"」欄位則其是由「"x"」欄位轉換為pl.Utf8格式後再加上_sub所組成。

其中的^就是約定語法中的上標語法,而^sup就是代表將sup置於上標位置。同理,_是約定語法中的下標語法,而_sub就是代表將sub置於下標位置。

此時如果針對「"sup"」及「"sub"」欄位使用GT.fmt_unit(),則此兩欄位將會以適當的上下標來呈現:

(
    GT(
        df.select(
            "x",
            sup=pl.col("x").cast(pl.Utf8).add("^sup"),
            sub=pl.col("x").cast(pl.Utf8).add("_sub"),
        )
    )
    .fmt_units(["sup", "sub"])
    .cols_align(align="right", columns=["sup", "sub"])
)

fmt unit

於Column label中使用約定語法

約定語法也可以在GT.cols_label()中使用。

舉例來說,我們可以建立一個「"area"」欄位,其值為「"x"」欄位與「"y"」欄位相乘而來:

(df.with_columns(area=pl.col("x").mul(pl.col("y"))).select("x", "y", "area"))
shape: (5, 3)
┌─────┬─────┬──────┐
│ x   ┆ y   ┆ area │
│ --- ┆ --- ┆ ---  │
│ i64 ┆ i64 ┆ i64  │
╞═════╪═════╪══════╡
│ 1   ┆ 63  ┆ 63   │
│ 2   ┆ 124 ┆ 248  │
│ 3   ┆ 219 ┆ 657  │
│ 4   ┆ 354 ┆ 1416 │
│ 5   ┆ 535 ┆ 2675 │
└─────┴─────┴──────

此時,如果我們想針對各欄位名稱添加單位,可以使用約定語法(註1)。例如:

(
    GT(
        df.with_columns(area=pl.col("x").mul(pl.col("y"))).select(
            "x", "y", "area"
        )
    ).cols_label(x="x(m)", y="y(m)", area="area({{mm^2}})")
)

unit notations column label

可以看到「"area"」欄位使用了約定語法{{mm^2}})來標示平方符號。

於Table spanner中使用約定語法

約定語法也可以在GT.tab_spanner()中使用。例如:

(
    GT(df)
    .cols_label(a2="{{a_2}}", a1="{{a_1}}", a0="{{a_0}}")
    .tab_spanner("y={{a_2}}{{x^2}}+{{a_1}}x+{{a_0}}", ["a2", "a1", "a0", "y"])
)

unit notations spanner

這裡我們使用約定語法來表達方程式中的多個變數及係數。

於任意component中使用約定語法

如果想要在其它component中使用約定語法的話,需要搭配define_units()define_units()gt提供的小工具,其有一個to_html()方法,可以將傳入的約定語法轉換為HTML輸出。

舉例來說,在GT.tab_header()中並不支援約定語法,所以下面這個表格的subtitle呈現結果不甚理想:

❌
(
    GT(df)
    .cols_label(a2="{{a_2}}", a1="{{a_1}}", a0="{{a_0}}")
    .tab_header(
        title="Linear Algebra", subtitle="y={{a_2}}{{x^2}}+{{a_1}}x+{{a_0}}"
    )
)

unit notations header ng

此時,我們可以利用define_units()來幫忙,其步驟如下:

  • 編寫一個u2html()來幫忙執行define_units().to_html()
  • 將使用約定語法的字串以u2html()包裹起來後,利用Python字串相加的功能來生成subtitle
  • 最後使用html()函數來包裹subtitle
def u2html(x) -> str:
    return define_units(x).to_html()


subtitle = (
    "y"
    + "="
    + u2html("{{a_2}}")
    + u2html("{{x^2}}")
    + "+"
    + u2html("{{a_1}}")
    + "x"
    + "+"
    + u2html("{{a_0}}")
)

(
    GT(df)
    .cols_label(a2="{{a_2}}", a1="{{a_1}}", a0="{{a_0}}")
    .tab_header(title="Linear Algebra", subtitle=html(subtitle))
)

unit notations header ok

這麼一來,運用類似的技巧,我們將可以在任何component中使用約定語法來呈現表格。

備註

註1:執筆之時,針對是否應該允許於column label中使用約定語法,gt團隊正於PR#446討論中,或可能於未來變更此行為。

Code

本日程式碼傳送門


上一篇
[Day12] - 格式化時間
下一篇
[Day14] - 顯示圖片
系列文
眾裏尋它:Python表格利器Great Tables30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言