iT邦幫忙

2024 iThome 鐵人賽

DAY 17
1

今天我們將以df DataFrame來說明一些還沒有提過的gt用法:

from datetime import date

import polars as pl
from great_tables import GT, from_column, google_font, loc, style, vals


df = pl.DataFrame(
    {
        "number": [0, 1, 2],
        "lang": ["python", "ruby", None],
        "color": ["red", "green", "blue"],
    }
)
shape: (3, 3)
┌────────┬────────┬───────┐
│ number ┆ lang   ┆ color │
│ ---    ┆ ---    ┆ ---   │
│ i64    ┆ str    ┆ str   │
╞════════╪════════╪═══════╡
│ 0      ┆ python ┆ red   │
│ 1      ┆ ruby   ┆ green │
│ 2      ┆ null   ┆ blue  │
└────────┴────────┴───────┘

關於Polars如何處理缺失值,建議您可以參考其文件

我們先來觀察一下,預設表格的渲染結果:

(
    GT(df)
    .tab_style(
        style=[style.borders(color="red", weight="3px")],
        locations=loc.body(columns="lang", rows=2),
    )
    .tab_style(
        style=[style.borders(color="purple", weight="3px")],
        locations=loc.body(columns="number", rows=0),
    )
)

default

這裡我們額外使用style.borders()標出兩個需要注意的格子:

  • 「"number"」欄的第一行為0(以紫色框標示)。
  • 「"lang"」欄的最後一行為None(以紅色框標示)。

GT.sub_missing()

GT.sub_missing(self, columns=None, rows=None, missing_text=None)

GT.sub_missing()可以讓我們取代欄位中的缺失值。例如:

(
    GT(df)
    .sub_missing()
    .tab_style(
        style=[style.borders(color="red", weight="3px")],
        locations=loc.body(columns="lang", rows=2),
    )
)

sub_missing default

預設的缺失填補值為HTML格式的—,也就是「"—"」。

我們可以使用missing_text參數來指定想填補的缺失值。例如:

(
    GT(df)
    .sub_missing(columns=["lang"], missing_text="😮")
    .tab_style(
        style=[style.borders(color="red", weight="3px")],
        locations=loc.body(columns="lang", rows=2),
    )
)

sub_missing missing_text

這裡我們使用「"😮"」來填補缺失值。

GT.sub_zero()

GT.sub_zero(self, columns=None, rows=None, zero_text='nil')

GT.sub_zero()可以讓我們取代欄位中的零值。例如:

(
    GT(df)
    .sub_zero()
    .tab_style(
        style=[style.borders(color="purple", weight="3px")],
        locations=loc.body(columns="number", rows=0),
    )
)

sub_zero default

預設的取代值為「"nil"」。

我們可以使用zero_text參數來指定想要的取代值。例如:

(
    GT(df)
    .sub_zero(columns=["number"], zero_text="ZERO")
    .tab_style(
        style=[
            style.borders(color="purple", weight="3px"),
            style.text(font=google_font("Merriweather")),
        ],
        locations=loc.body(columns="number", rows=0),
    )
)

sub_zero zero_text

這裡我們使用「"ZERO"」來作為取代值。

不知道眼尖的您有沒有發現,「"ZERO"」的字型好像跟其它欄位不太一樣。

因為此處使用了google_font()來指定其為「"Merriweather"」字型,是0.12.0版本的新功能。

from_column()

from_column(column, na_value=None, fn=None)

from_column()讓我們可以使用某一個欄位來指定顏色。例如:

(
    GT(df).tab_style(
        style=style.text(color=from_column("color")),
        locations=loc.body(columns=["number"]),
    )
)

06_from_column

這裡我們指定「"number"」欄內的字型顏色為「"color"」欄中標示的顏色。

下面這個例子則是指定「"number"」欄內的背景顏色為「"color"」欄中標示的顏色:

(
    GT(df).tab_style(
        style=style.fill(color=pl.col("color")),
        locations=loc.body(columns=["number"]),
    )
)

from_column polars

可是這裡面沒有from_column()呀?

沒錯,這是gt的一個特別功能,當傳入GT的DataFrame為Polars型態時,可以使用類似pl.col("color")的Polars expression來取代from_column()

vals

valsgt一個比較少人知道的功能。相比於GT.fmt_*()函數是針對一整欄進行格式化,vals是針對一個或數個目標進行格式化。

我們以下舉vals.fmt_number()vals.fmt_date()vals.fmt_image()三個例子說明。

vals.fmt_number()

vals.fmt_number(x, decimals=2, n_sigfig=None, drop_trailing_zeros=False, drop_trailing_dec_mark=True, use_seps=True, scale_by=1, compact=False, pattern='{x}', sep_mark=',', dec_mark='.', force_sign=False, locale=None)

vals.fmt_number()可以讓我們格式化一個或多個數值為整數。例如:

numbers = [100.1, 200.02, 300.033]
vals.fmt_number(numbers)
['100.10', '200.02', '300.03']

vals.fmt_date()

vals.fmt_date(x, date_style='iso', pattern='{x}', locale=None)

vals.fmt_date()可以讓我們將輸入格式化為日期。例如:

dates = [date(2024, 9, 1), date(2024, 10, 11)]
vals.fmt_date(dates, date_style="wd_m_day_year")
['Sun, Sep 1, 2024', 'Fri, Oct 11, 2024']

在沒有vals.fmt_date()的幫忙下,想得到類似的輸出,可以這麼做:

[d.strftime("%a, %b %d, %Y") for d in dates]
# or
[f"{d:%a, %b %d, %Y}" for d in dates]
['Sun, Sep 01, 2024', 'Fri, Oct 11, 2024']

這邊需留意vals.fmt_date()的日期是沒有前置的0,這是開發團隊所選擇的。

由於gt內部使用Babel來解析日期,所以理論上是可以添加任何想要的格式。如果您有想要使用其它目前不支援的格式,請回報至GitHub讓我們知道。

vals.fmt_image()

vals.fmt_image()可以讓我們利用類似GT.fmt_image()的方式來得到一或多個經過格式化的圖片。接著我們將此輸出以html()包裹後,即可於表格中任意component中顯示圖片。例如:

import polars as pl
from polars import selectors as cs
from great_tables import GT, vals, html
from importlib_resources import files


img_paths = files("great_tables") / "data/metro_images"

df = pl.DataFrame(
    {
        "col1": list("123"),
        "col2": list("123"),
        "col3": list("123"),
        "group": ["grp_a", "grp_a", "grp_b"],
        "row": ["row_1", "row_2", "row_3"],
    }
)

img1, img2, img3, img4, img5, img6 = vals.fmt_image(
    list("123456"), path=img_paths, file_pattern="metro_{}.svg"
)

(
    GT(df)
    .cols_label(**{"col1": html(img1), "col2": html(img2), "col3": html(img3)})
    .tab_stub(groupname_col="group", rowname_col="row")
    .tab_stubhead(html(img4))
    .tab_header(title=html(img5))
    .tab_source_note(html(img6))
    .fmt_image(cs.starts_with("col"), path=img_paths, file_pattern="metro_{}.svg")
)

vals fmt_image

我們使用vals.fmt_image()一次格式化六張位於gt repo中的圖片。接下來將其各自包裹上html()後,將圖片顯示於不同的component中。

Code

本日程式碼傳送門


上一篇
[Day16] - 生成概略趨勢圖(Nanoplot)
下一篇
[Day18] - 核心思維
系列文
眾裏尋它:Python表格利器Great Tables30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言