[ANN] PrettyTables.jl - Print formatted tables in Julia

Hi guys!

I want to announce a new package that I just submitted for registration. It is called PrettyTables.jl. The idea is to provide functionality to print data in tables in many formats. Currently, it supports only text tables like we have in the website ASCII Table Generator – Quickly format ASCII table. Great for source code comments and markdown!

I decided to code this package because I often need to print data in a human-readable format to analyze or to send to other people. You can see more about the package here: GitHub - ronisbr/PrettyTables.jl: Print data in formatted tables.

In the following, there are some examples of how the following data can be printed:

julia> data = ["Col. 1" "Col. 2" "Col. 3" "Col. 4";
                     1    false      1.0     0x01 ;
                     2     true      2.0     0x02 ;
                     3    false      3.0     0x03 ;
                     4     true      4.0     0x04 ;
                     5    false      5.0     0x05 ;
                     6     true      6.0     0x06 ;]

I am planning to improve the package given the community feedback!

69 Likes

Nice!

1 Like

Hi,

this is really nice package. If you are doing something complex like this, it would be great to have export to latex. We have just making fun with my colleagues that this is something all of as has written by themselves.

Another thing I would like would be highlighting of individual cells. For example to be able to highlight best value in a row. This is very useful when you are comparing different algorithms on different problems and you want to see, which one is the best one.

Thanks for a package,
Tomas

8 Likes

You mean like

?

1 Like

And https://github.com/korsbo/Latexify.jl

2 Likes

The dataframe printer is quite similar:

julia> DataFrame(Col1 = 1:6, Col2 = [false, true, false, true, false, true], Col3 = 1.0:6.0, Col4 = 0x01:0x06)
6Γ—4 DataFrame
β”‚ Row β”‚ Col1  β”‚ Col2  β”‚ Col3    β”‚ Col4  β”‚
β”‚     β”‚ Int64 β”‚ Bool  β”‚ Float64 β”‚ UInt8 β”‚
β”œβ”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€
β”‚ 1   β”‚ 1     β”‚ false β”‚ 1.0     β”‚ 0x01  β”‚
β”‚ 2   β”‚ 2     β”‚ true  β”‚ 2.0     β”‚ 0x02  β”‚
β”‚ 3   β”‚ 3     β”‚ false β”‚ 3.0     β”‚ 0x03  β”‚
β”‚ 4   β”‚ 4     β”‚ true  β”‚ 4.0     β”‚ 0x04  β”‚
β”‚ 5   β”‚ 5     β”‚ false β”‚ 5.0     β”‚ 0x05  β”‚
β”‚ 6   β”‚ 6     β”‚ true  β”‚ 6.0     β”‚ 0x06  β”‚

or GitHub - jacobadenbaum/TexTables.jl: Publication quality regression and statistical tables

1 Like

But DataFrames.jl does not allow to change to alignments of the cells, the format of the numbers that will be print, the color, etc. I see DataFrames as a container to store data. This simple package is just a β€œprinter” for data.

For example, when I try to use DataFrames to do this, the headers of the tables cannot have spaces. Hence I decided to do something that is supposed only to print data of matrices. Makes sense?

4 Likes

Good point!

What will be better: add some options like highlight_lowest, etc. or let the users control which cells they want to highlight using a matrix?

1 Like

You can have names with spaces, you just have to do Symbol("Name with multiple spaces)

1 Like

Yes. Using DataFrames, or worse depending on it, just to view your data is unpleasant.

julia> @time using DataFrames
  4.812422 seconds (11.94 M allocations: 620.775 MiB, 8.39% gc time)
julia> @time using PrettyTables
  0.149606 seconds (181.03 k allocations: 11.123 MiB, 11.44% gc time)

But, having an alternative DataFrames-like interface would make it easier for people to learn to use it.

3 Likes

Thanks!

Let me understand: do you mean create an interface to print DataTables or to add a interface equal to DataTables to print the information, so that we do not depend on DataTables?

This is very nice. Especially as table formats around have no good printing methods. Sometime I need to have data-frames only to get this functionalities and not for the processing of data. It means I do not have to do it anymore ? What functionalities do you want to offer with PrettyTables ?

From the other side, I am seeing lot of different table formats each trying to do same things. Somehow all this available Packages are generating confusion. Maybe this is due to my lower experience in Julia but I would assume it would be the same for other programming languages too.

Some consolidation of what is around feels to be necessary. Collecting the best features of different packages and having to import the wrapper packages which till take care of picking up the right functionalities.

1 Like

This is due to a necessity I have. I need to print on the screen or save in a file the data of a table in a human-readable format. I also often need to print the data formatted, like with 3 decimal digits. This is what I want this package to do.

I am not planning to add functionality to compute things, like DataFrames.jl have, like mean, standard deviation, etc. I want that this package remains simple to just print data on screen or save on text files.

Anyway, I am open to the community feedback!

This is not like the same, each one has its good and bad side. IMHO, I like diversity in open-source environment (not duplication). It helps to improve the language. What you should do is to download and try to see what fits you best :slight_smile:

If you find something that would be nice to add to a package that is already provided in another, then you can submit a PR or open an issue at this package to discuss the matter with the maintainers.

1 Like

I think I mean something like the second option:

import PrettyTables.pretty_table

function pretty_table(columns::AbstractVector{<:AbstractVector},
                      cnames::AbstractVector{Symbol})
    pretty_table(vcat(reshape(cnames, 1, :), Base.typed_hcat(Any, columns...)))
end
julia> pretty_table([rand(2), rand(Bool, 2), [:x, :y]], [:a, :b, :c])
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”
β”‚                   a β”‚    b β”‚ c β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€
β”‚  0.8906227251914487 β”‚ true β”‚ x β”‚
β”‚ 0.39124822148078553 β”‚ true β”‚ y β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”˜

Or using keyword options or something like that.

1 Like

Perfect! I can add it! :slight_smile:

1 Like

I really liked your suggestion. I have added support to what I called Highlighter. It is a structure that has three fields:

  • f: A function f(data,i,j) that should return true if the element (i,j) must be highlighted or false otherwise.
  • bold: If the highlight style should be bold.
  • color: The color of the highlight style.

Then we can have multiple highlight styles like in this example, in which I mark the maximum (blue) and minimum (red) values of the table considering the columns 1, 3, and 4:

7 Likes

Two questions (easily verifiable but I can’t test right now).

Does this implement the table interface (I believe TableTraits that many table packages use? I.e. if I put a DataFrame through this, will it pretty print?

In your code, I see you are using using Parameters, are you using any of the features that Parameters? As far as I know, @with_kw is now being tested in stdlib.

2 Likes

I was just advised by @dave.f.kleinschmidt to do precisely this!

And yes, I am using Parameters because it is way better if you want to take a pre-defined format and change just one thing.

Ok, now we have an initial interface with Tables.jl. Thus, we can now pretty print DataFrames.jl. However, I am no expert on this API. Can anyone please test with other packages?

9 Likes