thombashi / pytablewriter

pytablewriter is a Python library to write a table in various formats: AsciiDoc / CSV / Elasticsearch / HTML / JavaScript / JSON / LaTeX / LDJSON / LTSV / Markdown / MediaWiki / NumPy / Excel / Pandas / Python / reStructuredText / SQLite / TOML / TSV.
https://pytablewriter.rtfd.io/
MIT License
610 stars 43 forks source link

Comma-separate thousands or custom formatting in a column? #4

Closed hugovk closed 6 years ago

hugovk commented 6 years ago
import pytablewriter

data = [
    {"category": "2.6", "date": "2018-08-15", "downloads": 51},
    {"category": "2.7", "date": "2018-08-15", "downloads": 63749},
    {"category": "3.2", "date": "2018-08-15", "downloads": 2},
    {"category": "3.3", "date": "2018-08-15", "downloads": 40},
    {"category": "3.4", "date": "2018-08-15", "downloads": 6095},
    {"category": "3.5", "date": "2018-08-15", "downloads": 20358},
    {"category": "3.6", "date": "2018-08-15", "downloads": 35274},
    {"category": "3.7", "date": "2018-08-15", "downloads": 6595},
    {"category": "3.8", "date": "2018-08-15", "downloads": 3},
    {"category": "null", "date": "2018-08-15", "downloads": 1019},
]

writer = pytablewriter.MarkdownTableWriter()
writer.margin = 1

writer.header_list = sorted(set().union(*(d.keys() for d in data)))
writer.value_matrix = data

writer.write_table()

Produces:

category date downloads
2.6 2018-08-15 51
2.7 2018-08-15 63749
3.2 2018-08-15 2
3.3 2018-08-15 40
3.4 2018-08-15 6095
3.5 2018-08-15 20358
3.6 2018-08-15 35274
3.7 2018-08-15 6595
3.8 2018-08-15 3
null 2018-08-15 1019

I'd like the downloads to have comma-separated thousands to increase readability:

category date downloads
2.6 2018-08-15 51
2.7 2018-08-15 63,749
3.2 2018-08-15 2
3.3 2018-08-15 40
3.4 2018-08-15 6,095
3.5 2018-08-15 20,358
3.6 2018-08-15 35,274
3.7 2018-08-15 6,595
3.8 2018-08-15 3
null 2018-08-15 1,019

I can preprocess the data:

new_data = []

for row in data:
    row["downloads"] = "{:,}".format(row["downloads"])
    new_data.append(row)

data = new_data
category date downloads
2.6 2018-08-15 51
2.7 2018-08-15 63,749
3.2 2018-08-15 2
3.3 2018-08-15 40
3.4 2018-08-15 6,095
3.5 2018-08-15 20,358
3.6 2018-08-15 35,274
3.7 2018-08-15 6,595
3.8 2018-08-15 3
null 2018-08-15 1,019

And then explicitly right-format the column:

from pytablewriter import Align
writer.align_list = [Align.AUTO, Align.AUTO, Align.RIGHT]

# Or more generically:
writer.align_list = [Align.AUTO] * len(writer.header_list)
download_index = writer.header_list.index("downloads")
writer.align_list[download_index] = Align.RIGHT
category date downloads
2.6 2018-08-15 51
2.7 2018-08-15 63,749
3.2 2018-08-15 2
3.3 2018-08-15 40
3.4 2018-08-15 6,095
3.5 2018-08-15 20,358
3.6 2018-08-15 35,274
3.7 2018-08-15 6,595
3.8 2018-08-15 3
null 2018-08-15 1,019

But is there a neater way? Would some option to format numbers with comma-separated thousands be possible or sensible? Or perhaps custom formatting?

from pytablewriter import Format
writer.format_list = [None, None, Format.Comma]
writer.format_list = [None, None, "{:,}"]

That could cover cases that format numbers like 12 345.6 or 12.345,6, and also allow other formatting options.

Thank you.

thombashi commented 6 years ago

@hugovk Thank you for your feedback. Surely, number formatting specifier interface would be a nice feature. I will consider the feature for the future release (probably the next release).

jpiter commented 6 years ago

Upvoted. I am also looking for custom formatting options specifically for Latex tables. It would be nice to also be able to set Latex environments: \small, \tiny, etc.

thombashi commented 6 years ago

@hugovk I had add format_list attribute to specify formatting at pytablewriter 0.33.0. You can now specify comma-separated thousands more easily like the following:

from pytablewriter import MarkdownTableWriter, Format

data = [
    {"category": "2.6", "date": "2018-08-15", "downloads": 51},
    {"category": "2.7", "date": "2018-08-15", "downloads": 63749},
    {"category": "3.2", "date": "2018-08-15", "downloads": 2},
    {"category": "3.3", "date": "2018-08-15", "downloads": 40},
    {"category": "3.4", "date": "2018-08-15", "downloads": 6095},
    {"category": "3.5", "date": "2018-08-15", "downloads": 20358},
    {"category": "3.6", "date": "2018-08-15", "downloads": 35274},
    {"category": "3.7", "date": "2018-08-15", "downloads": 6595},
    {"category": "3.8", "date": "2018-08-15", "downloads": 3},
    {"category": "null", "date": "2018-08-15", "downloads": 1019},
]

writer = MarkdownTableWriter()
writer.margin = 1
writer.header_list = sorted(set().union(*(d.keys() for d in data)))
writer.value_matrix = data
writer.format_list = [Format.NONE, Format.NONE, Format.THOUSAND_SEPARATOR]

writer.write_table()
category date downloads
2.6 2018-08-15 51
2.7 2018-08-15 63,749
3.2 2018-08-15 2
3.3 2018-08-15 40
3.4 2018-08-15 6,095
3.5 2018-08-15 20,358
3.6 2018-08-15 35,274
3.7 2018-08-15 6,595
3.8 2018-08-15 3
null 2018-08-15 1,019

Any comments or suggestions would be appreciated.

thombashi commented 6 years ago

@jpiter Thank you for your comment. I will also consider style specifier option for the future release.

hugovk commented 6 years ago

@thombashi Thank you! I've tried it and that's perfect.

thombashi commented 6 years ago

@jpiter I had added style_list attribute to writers as an interface to set styles of columns (pytablewriter 0.34.0). You can set font size via the attribute. Usage is as follows:

Source Code

from pytablewriter import LatexTableWriter
from pytablewriter.style import Style, FontSize

writer = LatexTableWriter()
writer.table_name = "style test: font size"
writer.header_list = ["none", "empty_style", "tiny", "small", "medium", "large"]
writer.value_matrix = [[111, 111, 111, 111, 111, 111], [1234, 1234, 1234, 1234, 1234, 1234]]
writer.style_list = [
    None,
    Style(),
    Style(font_size=FontSize.TINY),
    Style(font_size=FontSize.SMALL),
    Style(font_size=FontSize.MEDIUM),
    Style(font_size=FontSize.LARGE),
]
writer.write_table()

Output

\begin{array}{r | r | r | r | r | r} \hline
    \verb|none| & \verb|empty_style| & \verb|tiny| & \verb|small| & \verb|medium| & \verb|large| \\ \hline
    \hline
     111 &         111 & \tiny 111 & \small 111 & \normalsize 111 & \large 111 \\ \hline
    1234 &        1234 & \tiny 1234 & \small 1234 & \normalsize 1234 & \large 1234 \\ \hline
\end{array}

note: styles can only be applicable for Latex/HTML writers

thombashi commented 6 years ago

I'll close the issue. Feel free to reopen if you still have any problems about the issue.

thombashi commented 5 years ago

I integrated format_list attribute into style_list attribute at pytablewriter 0.37.0. format_list can still be used (may be removed in the future release).

https://pytablewriter.readthedocs.io/en/latest/pages/examples/style/index.html

hugovk commented 5 years ago

Thank you! I've refactored my code to use style_list instead of align_list and format_list.