Giter Club home page Giter Club logo

great-tables's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

great-tables's Issues

Verify that `html()` and `md()` work everywhere

Let's double check everywhere that html and md could go is rendered correctly (and add tests).

We tested one case by snapshot testing create_body_component_h. That could be a good way to test the other places html() and md() could be used.

Ensure that `md()` helper works

Make md() work with tab_header(). Example:

import gt
from gt import exibble, countrypops, gtcars, md, html

from siuba import *

res = gtcars >> select(_.mfr, _.model, _.msrp) >> _.head(5)

gt.GT(res).tab_header(
    title=gt.md("Data listing from **gtcars**"), subtitle=gt.md("`gtcars` is an R dataset")
)

Ensure that the `html()` helper works

Similar to #13, we need to make the html() work with tab_header() (and other functions where new labels are accepted, eventually). Example:

import gt
from gt import exibble, countrypops, gtcars, md, html

from siuba import *

res = gtcars >> select(_.mfr, _.model, _.msrp) >> _.head(5)

gt.GT(res).tab_header(
    title=html("Data listing from <strong>gtcars</strong>"),
    subtitle=html("From <span style='color:red;'>gtcars</span>"),
)

Changelog in documentation page is not updated

Description

The changelog listed at this page shows the version v0.0.2 but the current version published to PyPI is v0.1.3

Reproducible example

Navigate to page and see.

Cursor_and_great_tables_-_Changelog

Expected result

Should show all the changelog up to v0.1.3

docs: add an example clinical trial report

@gshotwell mentioned it could be cool to create a shiny template for reporting clinical trials. Opening this issue to track creating some docs around this kind of thing.

Docs to write

Let's try writing some docs in this order:

  1. A simple example (not an app) on Great Table's doc site
  2. A shiny app (or template) that could go somewhere on the shiny docs (e.g. gallery, examples, or their templates repo). (Worse case, we could put it in our docs, etc..!)

Finding a good example

Are there any good examples of clinical reports, etc.. written for R gt?!

Example on website has commented code

Description

Example on website has commented code

Reproducible example

Navigate to examples page. Observe the code for Populations of Oceania's Countries

gt example has commented code

Expected result

If commented code is not relevant to the example, it should be removed.

Always exclude stub variables from selection

Since we can use polars selectors, like polars.selectors.all(), we need to remove stub variables from selection. Otherwise, we will erroneously try to include them in things like spanners.

epic: make pandas an optional dependency

Edit: polars support is complete! This issue now tracks only the removing of pandas as a mandatory dependency. This is largely a code cleanup activity, since the machinery to make pandas optional is already in great tables.

This may take a bit of work, but using the approach in https://github.com/machow/databackend, we should be able to make pandas and polars optional dependencies.

There is a data decorator pattern used in _tbl_data.py that wraps a dataframe to provide standard methods (e.g. for getting column names). We should be able to use generic functions, so gt can call things like get_column_names directly on any DataFrame.

Test use of polars selectors throughout library

Related to #34, I've implemented the path for using polars selectors, but need to add more tests of its usage. It seems like aspects of selection can be consolidated in places (e.g. the handling of columns in the cols_* functions).

Most functions that take a selection argument do a bit of custom checking, and these checks seem largely the same across functions..!

API coverage needed for public release

The following parts of the API need to be available for the public release:

Create Table

  • GT

Create or Modify Parts

  • tab_header()
  • tab_stubhead()
  • tab_spanner()
  • tab_source_note()
  • tab_options()

Format Data

  • fmt_number()
  • fmt_integer()
  • fmt_scientific()
  • fmt_percent()
  • fmt_currency()
  • fmt_bytes()
  • fmt_roman()
  • fmt_markdown()
  • fmt()

Modify Columns

  • cols_align()
  • cols_label()
  • cols_move_to_start()
  • cols_move_to_end()
  • cols_move()

Helper Functions

  • md()
  • html()
  • px()
  • pct()

Table Option Functions

  • opt_footnote_marks()
  • opt_row_striping()
  • opt_align_table_header()
  • opt_all_caps()

Datasets

  • countrypops
  • sza
  • gtcars
  • sp500
  • pizzaplace
  • exibble
  • towny
  • metro
  • constants
  • illness

Export Functions

  • as_raw_html()

Using row ID values in `rows` is inconsistent when the table has row groups

When the table has row groups, rows tend to lose their original ordering due to migration of rows to the different groups. This makes using a row index value in a rows argument less recommended (you have to know the pre-shuffled index). Using the row ID is the recommended way, however, this fails and it seems that the row ID maps to the wrong row. Here is an example of that using tab_style():

from great_tables import GT, md, style, loc
from great_tables.data import towny

towny_mini = towny[["name", "website", "land_area_km2", "csd_type"]].tail(4)

(
    GT(towny_mini, rowname_col="name", groupname_col="csd_type")
    .tab_style(
        style=style.fill(color="Beige"),
        locations=loc.body(columns="land_area_km2", rows=["Woodstock"]),
    )
)

Enable polars users to easily access to package datasets

Currently, great tables includes over a dozen datasets in its .data submodule:

# all datasets live in submodule
from great_tables.data import airquality, exibble, towny

# the exibble dataset can be fetched from the top-level
# which allows us to quickly churn out examples
from great_tables import exibble

However, these datasets are pandas DataFrames, so polars users need to convert them:

import polars as pl

pl.from_dataframe(exibble)

This isn't too bad. But maybe it could be better? This issue will discuss various ways we could approach loading data for both pandas and polars users.

This is mostly me thinking out loud about different options, without a strong opinion on an approach yet ๐Ÿ˜….

Possible approaches

  1. Leave as is. Polars folks use pl.from_pandas() to convert.
  2. Use options object to configure DataFrame constructor.
    • E.g. set_options(data_frame = pl.DataFrame).
    • E.g. set_options(data_frame="polars").
  3. Use functions to fetch each dataset. They could take a constructor argument.
    • E.g. exibble(pl.DataFrame), or
    • E.g. exibble("polars"), or
    • E.g. exibble() # uses set_options() to get DataFrame
  4. pandas and polars each gets its own data module.
    • E.g. from great_tables.data.polars import airquality, OR
    • E.g. from great_tables.data_pl import airquality, OR
    • E.g. from some_data_package import airquality

Desirable outcomes

  • Easy to perform
  • Helpful DataFrame completions in IDE

Easy to perform

For example, if data is simply imported and set_options() is used, then people will need to do some code in-between imports. This feels a cludgy.

Here's an example:

from great_tables import set_options

set_options(data_frame = "polars")

from great_tables.data import airquality

At the same time, calling functions gets kind of annoying:

from great_tables import GT, set_options
from great_tables.data import airquality

set_options(data_frame = "polars")

# annoying to call, but imports can be up top
# you can change the option and call airquality again
# to get data based on the current data_frame option
df_airquality = airquality()

# maybe the workaround is calling inside GT
GT(airquality())

Helpful DataFrame completions in IDE

I'm not sure how to implement something like set_options() and a data fetcher like airquality()? Is there a way to type it, so tools like pyright know that when an option is set to a specific value, that airquality() returns a specific type of DataFrame?

from great_tables import set_options
from great_tabels.data import airquality

set_options(data_frame = "polars")
airquality.<tab>                                           # shows polars methods

Last thoughts

I like the idea of us having a great_tables.data_pl submodule, or even a separate data package for datasets, but am curious what seems most useful to folks!

tab_source_note disappears when text is rendered as markdown

Description

tab_source_note disappears when text is rendered as markdown

Reproducible example

using

    .tab_source_note(
        source_note = "Source: The World Almanac and Book of Facts, 1975, page 406."
    )

renders the text correctly
great_tables_-_Examples
but adding

    .tab_source_note(
        source_note = md("Reference: McNeil, D. R. (1977) *Interactive Data Analysis*. Wiley.")
    )

Does not render the markdown and hides the text from the footnotes section

source code

from great_tables import GT, md, html
from great_tables.data import islands

islands_mini = islands.head(10)

(
    GT(islands_mini, rowname_col = "name")
    .tab_header(
        title = "Large Landmasses of the World",
        subtitle = "The top ten largest are presented"
    )
    .tab_source_note(
        source_note = "Source: The World Almanac and Book of Facts, 1975, page 406."
    )
    .tab_source_note(
        source_note = md("Reference: McNeil, D. R. (1977) *Interactive Data Analysis*. Wiley.")
    )
    . tab_stubhead(label = "landmass")
)

Expected result

Should render footnote with markdown when used in conjunction with the md tag

Development environment

  • Operating System: macOS
  • great_tables Version: 0.1.1

Additional context

This code is also displayed on the examples page

Ensure that row groups are rendered

Row groups can be defined in the GT class by setting a value on the "group_col" argument. Currently, it can be registered within the relevant object but the renderer responsible for body rows doesnโ€™t have this implementation.

Adding any code after the great-tables code in Quarto fails to render the great-tables table

Description

Adding any code after the great-tables code in Quarto fails to render the great-tables table

Reproducible example

use the following code:

from great_tables import GT
from great_tables.data import countrypops

import polars as pl
import polars.selectors as cs

# Get vectors of 2-letter country codes for each region of Oceania
countries = {
    "Australasia": ["AU", "NZ"],
    "Melanesia": ["NC", "PG", "SB", "VU"],
    "Micronesia": ["FM", "GU", "KI", "MH", "MP", "NR", "PW"],
    "Polynesia": ["PF", "WS", "TO", "TV"],
}

# a dictionary mapping region to country (e.g. AU -> Australasia)
region_to_country = {
    region: country for country, regions in countries.items() for region in regions
}

keep_rows = countrypops.country_code_2.isin(list(region_to_country)) & countrypops.year.isin(
    [2000, 2010, 2020]
)

# Create a gt table based on a preprocessed `countrypops`
wide_pops = (
    pl.from_pandas(countrypops)
    .filter(
        pl.col("country_code_2").is_in(list(region_to_country))
        & pl.col("year").is_in([2000, 2010, 2020])
    )
    .with_columns(pl.col("country_code_2").replace(region_to_country).alias("region"))
    .pivot(index=["country_name", "region"], columns="year", values="population")
    .sort("2020", descending=True)
)

(
    GT(wide_pops, rowname_col="country_name", groupname_col="region")
    .tab_header(title="Populations of Oceania's Countries in 2000, 2010, and 2020")
    .tab_spanner(label="Total Population", columns=cs.all())
    .fmt_integer()
)
print("extra lines")

Demo

gt print issue

Expected result

Should show the table followed by the print statement

Development environment

  • Operating System: macOS,
  • great_tables Version: 0.1.1

Lazy load example datasets

Currently, the data from gt is loaded whenever gt is imported.

We should be able to get lazy looking using one of these approaches

preferred: __getattr__ on the init module

gt/data/__init__.py

import pandas as pd


__all__ = (
    "countrypops",
    "sza",
)

countrypops: pd.DataFrame
    
def __getattr__(k):
    # lazy loading code goes here
    if k == "countrypops":
        print("Loading countrypops")
        ...

    ...

The one downside is that if we gt/__init__.py imports from gt.data, then this will import the data. In this case we'd also need to add __getattr__ handling in gt/__init__.py, which is starting to feel a bit much.

(In this case, we could also require people always import from gt.data, rather than top-level gt itself.)

Replace the data with functions that fetch data

Another common approach is that the data module contains functions, that when called load the data.

E.g. it would look like...

from gt.data import load_exibble

exibble = load_exibble()

This is commonly used to delay downloading the data.

using great_tables in shiny applications

Prework

Proposal

Hello there ๐Ÿ‘‹

I was trying to use great_tables in conjunction with shiny, and ended up figuring out a combination that works, something like ui.HTML(gt.GT(df)._repr_html()). However, it would be awesome if Shiny was a little smarter about handling GT objects.

Here's a reprex, using great-tables==0.1.0 and shiny==0.6.0.

from shiny import App, render, ui
import great_tables as gt

app_ui = ui.page_fluid(
    ui.output_ui("txt"),
)


def server(input, output, session):
    @output
    @render.ui
    def txt():
        return ui.HTML(gt.GT(gt.exibble)._repr_html_())

app = App(app_ui, server)

Does not render table markdown correctly when columns are formatted with GT.fmt_markdown

Description

Does not render table markdown correctly when columns are formatted with GT.fmt_markdown

Reproducible example

import pandas as pd
from great_tables import GT, md

from faker import Faker
import random

fake = Faker()

markdown_syntax = [
    "# Heading 1",
    "## Heading 2",
    "### Heading 3",
    "This is *italic* text.",
    "This is **bold** text.",
    "A [Click me](https://posit-dev.github.io/great-tables/articles/intro.html).",
    "- List item 1\n- List item 2\n- List item 3",
    "1. Ordered item 1\n2. Ordered item 2\n3. Ordered item 3",
    "```python\nprint('Hello, World!')\n```",
    """
    | Column 1      | Column2 |
    | ----------- | ----------- |
    | Row 1 Column 1     | Row 1 Column 2       |
    | Row 2 Column 1   | Row 2 Column 2        |
""",
"๐Ÿ˜…",
"I need to highlight these ==very important words==.",
"H~2~O",
"X^2^",
"- [x] Write the press release",
"![](https://www.google.com/logos/doodles/2023/seasonal-holidays-2023-6753651837110165.2-6752733080612634-cst.gif)",
"![](https://i.giphy.com/3oEjI4sFlp73fvEYgw.webp)",
"![](https://www.socialpilot.co/wp-content/uploads/2023/02/gif.gif)",
"""
> Blockquotes can be nested. Add a >> in front of the paragraph you want to nest.
>
>> Blockquotes can be nested. Add a >> in front of the paragraph you want to nest.
""",
"""
1. First item
2. Second item
3. Third item
    1. Indented item
    2. Indented item
4. Fourth item
""",
]

df = pd.DataFrame({'rendered markdown': markdown_syntax})
df['unrendered markdown'] = df['rendered markdown']

df['name'] = [fake.name() for _ in range(len(df))]
df['email'] = [fake.email() for _ in range(len(df))]
df['age'] = [fake.random_int(18, 99) for _ in range(len(df))]
df['is student'] = [fake.boolean() for _ in range(len(df))]
df['grade'] = [random.choice(['A', 'B', 'C', 'D', 'F']) for _ in range(len(df))]
df['gpa'] = [random.uniform(2.0, 4.0) for _ in range(len(df))]
df['date joined'] = [fake.date_this_decade() for _ in range(len(df))]
df_sorted_desc = df.sort_values(by='grade', ascending=True)

(
    GT(df_sorted_desc,rowname_col="name", groupname_col="grade")
    .fmt_markdown(columns="rendered markdown")
    .fmt_date(columns="date joined", date_style="m_day_year")
    .tab_spanner(
    label=md("<b><i>Personal Information</b></i>"),
    columns=["name", "email", "age", "grade", "gpa"],
    )
    .fmt_number(columns=["gpa"], decimals=2)
    .tab_stubhead(label="Students grouped by their grades")

)

Observe the cell where table markdown is rendered

Cursor_and_great-tables_Bug_bash

Expected result

Should render table markdown as a table.

Development environment

  • Operating System: macOS
  • great_tables Version: 0.1.1

Misplaced spanner label when there is a table stub

When there is a table stub (using rowname_col), the spanner label is set improperly. And the column labels are also affected. Code to reproduce:

import great_tables as gt

gtcars_mini = gt.gtcars[["model", "year", "hp", "trq"]].head(5)

gt.GT(gtcars_mini, rowname_col="model").tab_spanner(label=gt.md("*spanner*"), columns=["hp", "trq"])
spanner-issue

Add a formatting method that transforms URLs to links

For any cells containing URLs, we should have a fmt_url() method to make them navigable links. We should be careful to employ the method only on column containing URL text (though it is probably the user's responsibility to ensure this and that there are, for example, no URLs as part of a larger block of text).

We could expose options for how the links should be styled. They can be of the conventional style (with underlines and text coloring that sets it apart from other text), or, they can appear to be button-like (with a surrounding box that can be filled with a color).

URLs in data cells could be detected in two ways:

  • using the simple Markdown notation for URLs of the form: [label](URL)
  • assumes that the text is simply the URL

For the second case the URL is also used as the label but there is the option to use the label argument to modify that text.

How to use great_tables with shinylive?

The py-shiny docs use a tool called shinylive to run examples in the browser, via WASM. Let's use this issue to track what might be needed to use great_tables in shinylive.

The biggest challenge AFAICT is that great_tables depends on libsass-python, python bindings wrapping a C++ library.

Potential approaches

I have no idea how any of this works. This is me supplicating WASM wizards with my bad ideas:

  • Somehow get libsass-python working with WASM (e.g. see https://github.com/kwonoj/libsass-asm).
  • Use dart-sass somehow when we are in shinylive.
  • Rewrite the scss bits in great_table in python (or something else WASM-able). It seems like the use of scss is pretty simple--mostly for the variables, and one function.

Ensure that the stub is rendered

Currently the stub column can be defined in the GT class. However, itโ€™s not yet visible in the output HTML table. The renderer that handles body rows and column labels needs to be revised to implement this table location.

TypeError from a simple table render (from concatenation of int values)

A relatively simple table rendering yields a TypeError. Here's code that results in the error:

from great_tables import GT, md
from great_tables.data import constants

constants_mini = constants[["name", "value", "uncert", "sf_value", "sf_uncert", "units"]].tail(6)

GT(constants_mini, rowname_col="name", groupname_col="sf_value")

Results in the error:

TypeError: can only concatenate str (not "numpy.int64") to str

Option to export tables to LaTeX code

Prework

Proposal

It would be fantastic if there was an option to export tables to LaTeX as this would unlock a wide range of further uses in presentations, papers, and reports. For prior art, the original gt package in R does this, and pandas has a table export option.

Thanks for the great work on great tables!

Simplify console representation of GT

Currently, because GT is a dataclass, it just displays full representations of its attributes in the console. Because its attributes are also dataclasses, they do the same, so things get a bit unwieldy:

e.g.

GT(_tbl_data=   x color
0  1   red
1  2  blue, _body=<great_tables._gt_data.Body object at 0x163d31be0>, _boxhead=Boxhead([ColInfo(var='x', type=<ColInfoTypeEnum.default: 1>, column_label='x', column_align='right', column_width=None), ColInfo(var='color', type=<ColInfoTypeEnum.default: 1>, column_label='color', column_align='left', column_width=None)]), _stub=Stub([RowInfo(rownum_i=0, group_id=None, rowname=None, group_label=None, built=False), RowInfo(rownum_i=1, group_id=None, rowname=None, group_label=None, built=False)]), _row_groups=[], _group_rows=GroupRows([]), _spanners=Spanners([]), _heading=Heading(title=None, subtitle=None, preheader=None), _stubhead=None, _source_notes=[], _footnotes=[], _styles=[StyleInfo(locname='data', locnum=5, grpname=None, colname='x', rownum=0, colnum=None, styles=[CellStyleText(color='red', font=None, size=None, align=None, v_align=None, style=None, weight=None, stretch=None, decorate=None, transform=None, whitespace=None)]), StyleInfo(locname='data', locnum=5, grpname=None, colname='x', rownum=1, colnum=None, styles=[CellStyleText(color='blue', font=None, size=None, align=None, v_align=None, style=None, weight=None, stretch=None, decorate=None, transform=None, whitespace=None)])], _locale=<great_tables._gt_data.Locale object at 0x163d31130>, _formats=[], _options=Options(table_id=OptionsInfo(scss=False, category='table', type='value', value=None), table_caption=OptionsInfo(scss=False, category='table', type='value', value=None), table_width=OptionsInfo(scss=True, category='table', type='px', value='auto'), table_layout=OptionsInfo(scss=True, category='table', type='value', value='fixed'), table_margin_left=OptionsInfo(scss=True, category='table', type='px', value='auto'), table_margin_right=OptionsInfo(scss=True, category='table', type='px', value='auto'), table_background_color=OptionsInfo(scss=True, category='table', type='value', value='#FFFFFF'), table_additional_css=OptionsInfo(scss=False, category='table', type='values', value=None), table_font_names=OptionsInfo(scss=False, category='table', type='values', value=['-apple-system', 'BlinkMacSystemFont', 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Helvetica Neue', 'Fira Sans', 'Droid Sans', 'Arial', 'sans-serif']), table_font_size=OptionsInfo(scss=True, category='table', type='px', value='16px'), table_font_weight=OptionsInfo(scss=True, category='table', type='value', value='normal'), table_font_style=OptionsInfo(scss=True, category='table', type='value', value='normal'), table_font_color=OptionsInfo(scss=True, category='table', type='value', value='#333333'), table_font_color_light=OptionsInfo(scss=True, category='table', type='value', value='#FFFFFF'), table_border_top_include=OptionsInfo(scss=False, category='table', type='boolean', value=True), table_border_top_style=OptionsInfo(scss=True, category='table', type='value', value='solid'), table_border_top_width=OptionsInfo(scss=True, category='table', type='px', value='2px'), table_border_top_color=OptionsInfo(scss=True, category='table', type='value', value='#A8A8A8'), table_border_right_style=OptionsInfo(scss=True, category='table', type='value', value='none'), table_border_right_width=OptionsInfo(scss=True, category='table', type='px', value='2px'), table_border_right_color=OptionsInfo(scss=True, category='table', type='value', value='#D3D3D3'), table_border_bottom_include=OptionsInfo(scss=False, category='table', type='boolean', value=True), table_border_bottom_style=OptionsInfo(scss=True, category='table', type='value', value='solid'), table_border_bottom_width=OptionsInfo(scss=True, category='table', type='px', value='2px'), table_border_bottom_color=OptionsInfo(scss=True, category='table', type='value', value='#A8A8A8'), table_border_left_style=OptionsInfo(scss=True, category='table', type='value', value='none'), table_border_left_width=OptionsInfo(scss=True, category='table', type='px', value='2px'), table_border_left_color=OptionsInfo(scss=True, category='table', type='value', value='#D3D3D3'), heading_background_color=OptionsInfo(scss=True, category='heading', type='value', value=None), heading_align=OptionsInfo(scss=True, category='heading', type='value', value='center'), heading_title_font_size=OptionsInfo(scss=True, category='heading', type='px', value='125%'), heading_title_font_weight=OptionsInfo(scss=True, category='heading', type='value', value='initial'), heading_subtitle_font_size=OptionsInfo(scss=True, category='heading', type='px', value='85%'), heading_subtitle_font_weight=OptionsInfo(scss=True, category='heading', type='value', value='initial'), heading_padding=OptionsInfo(scss=True, category='heading', type='px', value='4px'), heading_padding_horizontal=OptionsInfo(scss=True, category='heading', type='px', value='5px'), heading_border_bottom_style=OptionsInfo(scss=True, category='heading', type='value', value='solid'), heading_border_bottom_width=OptionsInfo(scss=True, category='heading', type='px', value='2px'), heading_border_bottom_color=OptionsInfo(scss=True, category='heading', type='value', value='#D3D3D3'), heading_border_lr_style=OptionsInfo(scss=True, category='heading', type='value', value='none'), heading_border_lr_width=OptionsInfo(scss=True, category='heading', type='px', value='1px'), heading_border_lr_color=OptionsInfo(scss=True, category='heading', type='value', value='#D3D3D3'), column_labels_background_color=OptionsInfo(scss=True, category='column_labels', type='value', value=None), column_labels_font_size=OptionsInfo(scss=True, category='column_labels', type='px', value='100%'), column_labels_font_weight=OptionsInfo(scss=True, category='column_labels', type='value', value='normal'), column_labels_text_transform=OptionsInfo(scss=True, category='column_labels', type='value', value='inherit'), column_labels_padding=OptionsInfo(scss=True, category='column_labels', type='px', value='5px'), column_labels_padding_horizontal=OptionsInfo(scss=True, category='column_labels', type='px', value='5px'), column_labels_vlines_style=OptionsInfo(scss=True, category='table_body', type='value', value='none'), column_labels_vlines_width=OptionsInfo(scss=True, category='table_body', type='px', value='1px'), column_labels_vlines_color=OptionsInfo(scss=True, category='table_body', type='value', value='#D3D3D3'), column_labels_border_top_style=OptionsInfo(scss=True, category='column_labels', type='value', value='solid'), column_labels_border_top_width=OptionsInfo(scss=True, category='column_labels', type='px', value='2px'), column_labels_border_top_color=OptionsInfo(scss=True, category='column_labels', type='value', value='#D3D3D3'), column_labels_border_bottom_style=OptionsInfo(scss=True, category='column_labels', type='value', value='solid'), column_labels_border_bottom_width=OptionsInfo(scss=True, category='column_labels', type='px', value='2px'), column_labels_border_bottom_color=OptionsInfo(scss=True, category='column_labels', type='value', value='#D3D3D3'), column_labels_border_lr_style=OptionsInfo(scss=True, category='column_labels', type='value', value='none'), column_labels_border_lr_width=OptionsInfo(scss=True, category='column_labels', type='px', value='1px'), column_labels_border_lr_color=OptionsInfo(scss=True, category='column_labels', type='value', value='#D3D3D3'), column_labels_hidden=OptionsInfo(scss=False, category='column_labels', type='boolean', value=False), row_group_background_color=OptionsInfo(scss=True, category='row_group', type='value', value=None), row_group_font_size=OptionsInfo(scss=True, category='row_group', type='px', value='100%'), row_group_font_weight=OptionsInfo(scss=True, category='row_group', type='value', value='initial'), row_group_text_transform=OptionsInfo(scss=True, category='row_group', type='value', value='inherit'), row_group_padding=OptionsInfo(scss=True, category='row_group', type='px', value='8px'), row_group_padding_horizontal=OptionsInfo(scss=True, category='row_group', type='px', value='5px'), row_group_border_top_style=OptionsInfo(scss=True, category='row_group', type='value', value='solid'), row_group_border_top_width=OptionsInfo(scss=True, category='row_group', type='px', value='2px'), row_group_border_top_color=OptionsInfo(scss=True, category='row_group', type='value', value='#D3D3D3'), row_group_border_right_style=OptionsInfo(scss=True, category='row_group', type='value', value='none'), row_group_border_right_width=OptionsInfo(scss=True, category='row_group', type='px', value='1px'), row_group_border_right_color=OptionsInfo(scss=True, category='row_group', type='value', value='#D3D3D3'), row_group_border_bottom_style=OptionsInfo(scss=True, category='row_group', type='value', value='solid'), row_group_border_bottom_width=OptionsInfo(scss=True, category='row_group', type='px', value='2px'), row_group_border_bottom_color=OptionsInfo(scss=True, category='row_group', type='value', value='#D3D3D3'), row_group_border_left_style=OptionsInfo(scss=True, category='row_group', type='value', value='none'), row_group_border_left_width=OptionsInfo(scss=True, category='row_group', type='px', value='1px'), row_group_border_left_color=OptionsInfo(scss=True, category='row_group', type='value', value='#D3D3D3'), row_group_default_label=OptionsInfo(scss=False, category='row_group', type='value', value=None), row_group_as_column=OptionsInfo(scss=False, category='row_group', type='boolean', value=False), table_body_hlines_style=OptionsInfo(scss=True, category='table_body', type='value', value='solid'), table_body_hlines_width=OptionsInfo(scss=True, category='table_body', type='px', value='1px'), table_body_hlines_color=OptionsInfo(scss=True, category='table_body', type='value', value='#D3D3D3'), table_body_vlines_style=OptionsInfo(scss=True, category='table_body', type='value', value='none'), table_body_vlines_width=OptionsInfo(scss=True, category='table_body', type='px', value='1px'), table_body_vlines_color=OptionsInfo(scss=True, category='table_body', type='value', value='#D3D3D3'), table_body_border_top_style=OptionsInfo(scss=True, category='table_body', type='value', value='solid'), table_body_border_top_width=OptionsInfo(scss=True, category='table_body', type='px', value='2px'), table_body_border_top_color=OptionsInfo(scss=True, category='table_body', type='value', value='#D3D3D3'), table_body_border_bottom_style=OptionsInfo(scss=True, category='table_body', type='value', value='solid'), table_body_border_bottom_width=OptionsInfo(scss=True, category='table_body', type='px', value='2px'), table_body_border_bottom_color=OptionsInfo(scss=True, category='table_body', type='value', value='#D3D3D3'), data_row_padding=OptionsInfo(scss=True, category='data_row', type='px', value='8px'), data_row_padding_horizontal=OptionsInfo(scss=True, category='data_row', type='px', value='5px'), stub_background_color=OptionsInfo(scss=True, category='stub', type='value', value=None), stub_font_size=OptionsInfo(scss=True, category='stub', type='px', value='100%'), stub_font_weight=OptionsInfo(scss=True, category='stub', type='value', value='initial'), stub_text_transform=OptionsInfo(scss=True, category='stub', type='value', value='inherit'), stub_border_style=OptionsInfo(scss=True, category='stub', type='value', value='solid'), stub_border_width=OptionsInfo(scss=True, category='stub', type='px', value='2px'), stub_border_color=OptionsInfo(scss=True, category='stub', type='value', value='#D3D3D3'), stub_row_group_background_color=OptionsInfo(scss=True, category='stub', type='value', value=None), stub_row_group_font_size=OptionsInfo(scss=True, category='stub', type='px', value='100%'), stub_row_group_font_weight=OptionsInfo(scss=True, category='stub', type='value', value='initial'), stub_row_group_text_transform=OptionsInfo(scss=True, category='stub', type='value', value='inherit'), stub_row_group_border_style=OptionsInfo(scss=True, category='stub', type='value', value='solid'), stub_row_group_border_width=OptionsInfo(scss=True, category='stub', type='px', value='2px'), stub_row_group_border_color=OptionsInfo(scss=True, category='stub', type='value', value='#D3D3D3'), summary_row_padding=OptionsInfo(scss=True, category='summary_row', type='px', value='8px'), summary_row_padding_horizontal=OptionsInfo(scss=True, category='summary_row', type='px', value='5px'), summary_row_background_color=OptionsInfo(scss=True, category='summary_row', type='value', value=None), summary_row_text_transform=OptionsInfo(scss=True, category='summary_row', type='value', value='inherit'), summary_row_border_style=OptionsInfo(scss=True, category='summary_row', type='value', value='solid'), summary_row_border_width=OptionsInfo(scss=True, category='summary_row', type='px', value='2px'), summary_row_border_color=OptionsInfo(scss=True, category='summary_row', type='value', value='#D3D3D3'), grand_summary_row_padding=OptionsInfo(scss=True, category='grand_summary_row', type='px', value='8px'), grand_summary_row_padding_horizontal=OptionsInfo(scss=True, category='grand_summary_row', type='px', value='5px'), grand_summary_row_background_color=OptionsInfo(scss=True, category='grand_summary_row', type='value', value=None), grand_summary_row_text_transform=OptionsInfo(scss=True, category='grand_summary_row', type='value', value='inherit'), grand_summary_row_border_style=OptionsInfo(scss=True, category='grand_summary_row', type='value', value='double'), grand_summary_row_border_width=OptionsInfo(scss=True, category='grand_summary_row', type='px', value='6px'), grand_summary_row_border_color=OptionsInfo(scss=True, category='grand_summary_row', type='value', value='#D3D3D3'), footnotes_font_size=OptionsInfo(scss=True, category='footnotes', type='px', value='90%'), footnotes_padding=OptionsInfo(scss=True, category='footnotes', type='px', value='4px'), footnotes_padding_horizontal=OptionsInfo(scss=True, category='footnotes', type='px', value='5px'), footnotes_background_color=OptionsInfo(scss=True, category='footnotes', type='value', value=None), footnotes_margin=OptionsInfo(scss=True, category='footnotes', type='px', value='0px'), footnotes_border_bottom_style=OptionsInfo(scss=True, category='footnotes', type='value', value='none'), footnotes_border_bottom_width=OptionsInfo(scss=True, category='footnotes', type='px', value='2px'), footnotes_border_bottom_color=OptionsInfo(scss=True, category='footnotes', type='value', value='#D3D3D3'), footnotes_border_lr_style=OptionsInfo(scss=True, category='footnotes', type='value', value='none'), footnotes_border_lr_width=OptionsInfo(scss=True, category='footnotes', type='px', value='2px'), footnotes_border_lr_color=OptionsInfo(scss=True, category='footnotes', type='value', value='#D3D3D3'), footnotes_marks=OptionsInfo(scss=False, category='footnotes', type='values', value='numbers'), footnotes_multiline=OptionsInfo(scss=False, category='footnotes', type='boolean', value=True), footnotes_sep=OptionsInfo(scss=False, category='footnotes', type='value', value=' '), source_notes_padding=OptionsInfo(scss=True, category='source_notes', type='px', value='4px'), source_notes_padding_horizontal=OptionsInfo(scss=True, category='source_notes', type='px', value='5px'), source_notes_background_color=OptionsInfo(scss=True, category='source_notes', type='value', value=None), source_notes_font_size=OptionsInfo(scss=True, category='source_notes', type='px', value='90%'), source_notes_border_bottom_style=OptionsInfo(scss=True, category='source_notes', type='value', value='none'), source_notes_border_bottom_width=OptionsInfo(scss=True, category='source_notes', type='px', value='2px'), source_notes_border_bottom_color=OptionsInfo(scss=True, category='source_notes', type='value', value='#D3D3D3'), source_notes_border_lr_style=OptionsInfo(scss=True, category='source_notes', type='value', value='none'), source_notes_border_lr_width=OptionsInfo(scss=True, category='source_notes', type='px', value='2px'), source_notes_border_lr_color=OptionsInfo(scss=True, category='source_notes', type='value', value='#D3D3D3'), source_notes_multiline=OptionsInfo(scss=False, category='source_notes', type='boolean', value=True), source_notes_sep=OptionsInfo(scss=False, category='source_notes', type='value', value=' '), row_striping_background_color=OptionsInfo(scss=True, category='row', type='value', value='rgba(128,128,128,0.05)'), row_striping_include_stub=OptionsInfo(scss=False, category='row', type='boolean', value=False), row_striping_include_table_body=OptionsInfo(scss=False, category='row', type='boolean', value=False), container_width=OptionsInfo(scss=False, category='container', type='px', value='auto'), container_height=OptionsInfo(scss=False, category='container', type='px', value='auto'), container_padding_x=OptionsInfo(scss=False, category='container', type='px', value='0px'), container_padding_y=OptionsInfo(scss=False, category='container', type='px', value='10px'), container_overflow_x=OptionsInfo(scss=False, category='container', type='overflow', value='auto'), container_overflow_y=OptionsInfo(scss=False, category='container', type='overflow', value='auto'), page_orientation=OptionsInfo(scss=False, category='page', type='value', value='portrait'), page_numbering=OptionsInfo(scss=False, category='page', type='boolean', value=False), page_header_use_tbl_headings=OptionsInfo(scss=False, category='page', type='boolean', value=False), page_footer_use_tbl_notes=OptionsInfo(scss=False, category='page', type='boolean', value=False), page_width=OptionsInfo(scss=False, category='page', type='value', value='8.5in'), page_height=OptionsInfo(scss=False, category='page', type='value', value='11.0in'), page_margin_left=OptionsInfo(scss=False, category='page', type='value', value='1.0in'), page_margin_right=OptionsInfo(scss=False, category='page', type='value', value='1.0in'), page_margin_top=OptionsInfo(scss=False, category='page', type='value', value='1.0in'), page_margin_bottom=OptionsInfo(scss=False, category='page', type='value', value='1.0in'), page_header_height=OptionsInfo(scss=False, category='page', type='value', value='0.5in'), page_footer_height=OptionsInfo(scss=False, category='page', type='value', value='0.5in'), quarto_disable_processing=OptionsInfo(scss=False, category='quarto', type='logical', value=False), quarto_use_bootstrap=OptionsInfo(scss=False, category='quarto', type='logical', value=False)), _has_built=False)

Let's simplify the representation in the console a bit by:

  • showing all the parts of the GT object (e.g. _styles)
  • BUT give a summary of each part (e.g. number of items in _styles, rather than showing each one)
    • Alternatively, we could show most of the first and last items, etc..

Note that this likely isn't too critical, since ideally people are developing somewhere they can preview the HTML output (similar to developing a plot), but may be useful for debugging

Test options API

It looks like the options API in gt/_options.py does not have any tests yet. Opening this issue to track adding tests. I've refactored OptionsAPI out in #50, so may be useful to add tests just before merging or right after

Avoid pandas "trying to set a copy on a slice" warning

We should just need to change occurrences of some_df[col][row] = some_value with some_df.loc[row, col] = some_value.

Note that in both cases the row is being specified using an index value (e.g. 0 is not position 0, but matches any 0 in the pandas index). To select by position, we'll need to use .iloc. Weirdly, this then means that we'll need to select the column by position as well (e.g. 7 rather than a string name), but isn't too hard to do..!

Selection sometimes fails for DataFrames with integer named columns and a function selector

Will clean up a bit, but was triggered by this code:

from great_tables import GT, countrypops

# Get vectors of 2-letter country codes for each region of Oceania
countries = {
    "Australasia": ["AU", "NZ"],
    "Melanesia":  ["NC", "PG", "SB", "VU"],
    "Micronesia": ["FM", "GU", "KI", "MH", "MP", "NR", "PW"],
    "Polynesia": ["PF", "WS", "TO", "TV"],
}

# a dictionary mapping region to country (e.g. AU -> Australasia)
region_to_country = {
    region: country
    for country, regions in countries.items()
    for region in regions
}

keep_rows = (
    countrypops.country_code_2.isin(list(region_to_country))
    & countrypops.year.isin([2000, 2010, 2020])
)

# Create a gt table based on a preprocessed `countrypops`
wide_pops = (countrypops[keep_rows]
    .assign(region = lambda D: D.country_code_2.map(region_to_country))
    .pivot_table(index = ["country_name", "region"], columns = "year", values = "population")
    .reset_index()
    .sort_values(2020, ascending = False)
)

(
    GT(wide_pops, rowname_col = "country_name", groupname_col = "region")
    .tab_header(title ="Populations of Oceania's Countries in 2000, 2010, and 2020")
    .tab_spanner(
        label = "Total Population",
        columns = lambda colname: True
    )
    .fmt_integer()
)

Essentially, tab_spanner correctly selects columns using the lambda, but then it passes those columns to cols_move. However, because some of the cols it selected are integers (e.g. 2000), cols_move interprets these as column positions :/

when multiple styles specified in single tab_style call, only first is applied

It appears that when multiple styles are specified in a tab_style call, only the first appears.

from great_tables import GT
from great_tables.data import airquality

gt_air = GT(airquality.head())

gt_air.tab_style(
    [style.fill("yellow"), style.borders(sides = "all")],
    loc.body("Temp", [1, 2])
)
image

Note that if you switch the styles in the list around, it seems like only the first appears.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.