Format chemical formulas.
GT.fmt_chem(
columns=None,
rows=None,
)
With fmt_chem() you can format chemical formulas and reactions in the table body. Often the input text will be in a common form representing single compounds (like "C2H4O" for acetaldehyde) but chemical reactions can also be used (e.g., "2 CH3OH -> CH3OCH3 + H2O"). So long as the text within the targeted cells conforms to the specialized chemistry notation, the appropriate conversions will occur. Details on chemistry notation can be found in the section entitled How to use chemistry notation.
Parameters
columns: SelectExpr = None
-
The columns to target. Can either be a single column name or a series of column names provided in a list.
rows: int | list[int] | None = None
-
In conjunction with
columns=, we can specify which of their rows should undergo formatting. The default is all rows, resulting in all rows in targeted columns being formatted. Alternatively, we can supply a list of row indices.
Returns
GT
-
The GT object is returned. This is the same object that the method is called on so that we can facilitate method chaining.
How To Use Chemistry Notation
The chemistry notation involves a shorthand for writing chemical formulas and reactions. It should feel familiar in its basic usage and the more advanced typesetting tries to limit the amount of syntax needed. Here are examples of the supported features:
"CH3O2" and "(NH4)2S" will render with subscripted numerals
Charges can be expressed with terminating "+" or "-", as in "H+" and "[AgCl2]-"; numbered charges use: "CrO4^2-", "Fe^n+", "Y^99+", or "Y^{99+}"
Stoichiometric values can prepend formulas: "2H2O2", "2 H2O2", "0.5 H2O", "1/2 H2O", "(1/2) H2O"
Certain standalone lowercase letters are automatically italicized: "NO_x" and "x Na(NH4)HPO4" will have italic x characters; you can always italicize with "*" (as in "*n* H2O")
Chemical isotopes can be rendered as: "^{227}_{90}Th" or "^227_90Th"; nuclides are similar: "^{0}_{-1}n^{-}", "^0_-1n-"
Chemical reactions can use "+" signs and a variety of reaction arrows: "->", "<-", "<->", "<-->", "<=>", "<=>>", "<<=>"
Center dots (for addition compounds) use a single "." or "*" surrounded by spaces: "KCr(SO4)2 . 12 H2O" or "KCr(SO4)2 * 12 H2O"
Single and double bonds between adjacent characters use "-" or "=": "C6H5-CHO", "CH3CH=CH2"
Greek letters can be inserted using colon notation: ":delta: ^13C"
Examples
Let’s use the reactions dataset and create a table of gas-phase reaction rate constants for selected terminal alkenes. The cmpd_formula column contains chemical formulas and fmt_chem() will render them with properly subscripted numerals. Notice that the column labels for O₃ and NO₃ use the {%...%} chemistry notation within cols_label().
import polars as pl
import polars.selectors as cs
from great_tables import GT, data
reactions_mini = (
data.pl.reactions
.filter(
(pl.col("cmpd_type") == "terminal monoalkene")
& pl.col("cmpd_name").str.starts_with("1-")
)
.select("cmpd_name", "cmpd_formula", cs.ends_with("k298"))
)
(
GT(reactions_mini)
.tab_header(title="Gas-Phase Reactions of Selected Terminal Alkenes")
.tab_spanner(
label="Reaction Rate Constant at 298 K",
columns=cs.ends_with("k298"),
)
.fmt_chem(columns="cmpd_formula")
.fmt_scientific(columns=cs.ends_with("k298"))
.sub_missing()
.cols_label(
cmpd_name="Alkene",
cmpd_formula="Formula",
OH_k298="OH",
O3_k298="{{%O3%}}",
NO3_k298="{{%NO3%}}",
Cl_k298="Cl",
)
.opt_align_table_header(align="left")
)
| Gas-Phase Reactions of Selected Terminal Alkenes |
| Alkene |
Formula |
Reaction Rate Constant at 298 K
|
| OH |
O3 |
NO3 |
Cl |
| 1-butene |
C4H8 |
3.10 × 10−11 |
1.00 × 10−17 |
1.30 × 10−14 |
3.00 × 10−10 |
| 1-pentene |
C5H10 |
3.22 × 10−11 |
1.06 × 10−17 |
1.50 × 10−14 |
4.20 × 10−10 |
| 1-hexene |
C6H12 |
3.70 × 10−11 |
1.15 × 10−17 |
1.80 × 10−14 |
4.00 × 10−10 |
| 1-heptene |
C7H14 |
3.88 × 10−11 |
1.16 × 10−17 |
2.00 × 10−14 |
4.40 × 10−10 |
| 1-octene |
C8H16 |
3.44 × 10−11 |
1.01 × 10−17 |
2.50 × 10−14 |
5.50 × 10−10 |
| 1-nonene |
C9H18 |
4.32 × 10−11 |
9.90 × 10−18 |
— |
5.90 × 10−10 |
| 1-decene |
C10H20 |
4.61 × 10−11 |
1.11 × 10−17 |
2.60 × 10−14 |
— |
| 1-undecene |
C11H22 |
4.79 × 10−11 |
1.03 × 10−17 |
— |
— |
| 1-dodecene |
C12H24 |
5.03 × 10−11 |
1.03 × 10−17 |
2.80 × 10−14 |
— |
| 1-tridecene |
C13H26 |
5.09 × 10−11 |
9.60 × 10−18 |
— |
— |
| 1-tetradecene |
C14H28 |
4.96 × 10−11 |
9.70 × 10−18 |
2.80 × 10−14 |
— |
The photolysis dataset contains photolysis pathways where both the cmpd_formula and products columns hold chemistry notation. We can format both columns with fmt_chem() and use cols_merge() to combine the compound name with its formatted formula.
photolysis_mini = (
data.pl.photolysis
.filter(pl.col("cmpd_name").is_in([
"hydrogen peroxide", "nitrous acid",
"nitric acid", "acetaldehyde",
"methyl peroxide", "methyl nitrate",
"ethyl nitrate", "isopropyl nitrate",
]))
.select(pl.exclude("l", "m", "n", "quantum_yield", "type"))
)
(
GT(photolysis_mini)
.tab_header(title="Photolysis Pathways of Selected VOCs")
.fmt_chem(columns=["cmpd_formula", "products"])
.cols_merge(
columns=["cmpd_name", "cmpd_formula"],
pattern="{0}, {1}",
)
.cols_label(cmpd_name="Compound", products="Products")
.cols_hide(columns=["wavelength_nm", "sigma_298_cm2"])
.opt_align_table_header(align="left")
)
| Photolysis Pathways of Selected VOCs |
| Compound |
Products |
| hydrogen peroxide, H2O2 |
→ OH + OH |
| nitrous acid, HONO |
→ OH + NO |
| nitric acid, HNO3 |
→ OH + NO2 |
| acetaldehyde, CH3CHO |
→ HCO + CH3 |
| methyl peroxide, CH3OOH |
→ CH3O + OH |
| methyl nitrate, CH3ONO2 |
→ CH3O + NO2 |
| ethyl nitrate, C2H5ONO2 |
→ C2H5O + NO2 |
| isopropyl nitrate, i-C3H7ONO2 |
→ i-C3H7O + NO2 |
The nuclides dataset contains isotope data with nuclide notation (e.g., "^{12}_{6}C") that fmt_chem() renders with properly overstruck mass and atomic numbers. Here we show isotopes of hydrogen and carbon.
from great_tables import md
nuclides_mini = (
data.pl.nuclides
.filter(pl.col("element").is_in(["H", "C"]))
.with_columns(pl.col("nuclide").str.replace(r"[0-9]+$", ""))
.select("nuclide", "atomic_mass", "half_life", "decay_1", "is_stable")
)
stable = (
nuclides_mini.with_row_index()
.filter(pl.col("is_stable") == "TRUE")["index"].to_list()
)
unstable = (
nuclides_mini.with_row_index()
.filter(pl.col("is_stable") == "FALSE")["index"].to_list()
)
(
GT(nuclides_mini, rowname_col="nuclide")
.tab_header(title="Isotopes of Hydrogen and Carbon")
.tab_stubhead(label="Isotope")
.fmt_chem(columns="nuclide")
.fmt_scientific(columns="half_life")
.fmt_number(columns="atomic_mass", decimals=4, scale_by=1 / 1e6)
.sub_missing(
columns="half_life", rows=stable, missing_text=md("**STABLE**")
)
.sub_missing(columns="half_life", rows=unstable)
.sub_missing(columns="decay_1")
.cols_hide(columns="is_stable")
.cols_align(align="center", columns="decay_1")
.cols_label(decay_1="Decay Mode")
.opt_align_table_header(align="left")
.opt_vertical_padding(scale=0.5)
)
| Isotopes of Hydrogen and Carbon |
| Isotope |
atomic_mass |
half_life |
Decay Mode |
1 1H |
1.0078 |
STABLE |
— |
2 1H |
2.0141 |
STABLE |
— |
3 1H |
3.0160 |
3.89 × 108 |
B- |
4 1H |
4.0264 |
— |
N |
5 1H |
5.0353 |
8.61 × 10−23 |
2N |
6 1H |
6.0450 |
2.94 × 10−22 |
— |
7 1H |
7.0527 |
5.07 × 10−21 |
— |
8 6C |
8.0376 |
3.51 × 10−21 |
2P |
9 6C |
9.0310 |
1.26 × 10−1 |
EC+B+ |
10 6C |
10.0169 |
1.93 × 101 |
EC+B+ |
11 6C |
11.0114 |
1.22 × 103 |
EC+B+ |
12 6C |
12.0000 |
STABLE |
— |
13 6C |
13.0034 |
STABLE |
— |
14 6C |
14.0032 |
1.80 × 1011 |
B- |
15 6C |
15.0106 |
2.45 |
B- |
16 6C |
16.0147 |
7.47 × 10−1 |
B- |
17 6C |
17.0226 |
1.93 × 10−1 |
B- |
18 6C |
18.0268 |
9.20 × 10−2 |
B- |
19 6C |
19.0348 |
4.63 × 10−2 |
B- |
20 6C |
20.0403 |
1.63 × 10−2 |
B- |
22 6C |
22.0576 |
6.10 × 10−3 |
B- |