jazzband / prettytable

Display tabular data in a visually appealing ASCII table format
https://pypi.org/project/PrettyTable/
Other
1.35k stars 154 forks source link

float_format does not seem to work #243

Open andrea-cassioli-maersk opened 1 year ago

andrea-cassioli-maersk commented 1 year ago

What did you do?

I would like to setup the float format for the whole table using the float_format option in the PrettyTable class constructor.

I have tried several values, but either I get an error because the value is not a float format string (fair), or nothing happens.

What did you expect to happen?

|        Metric |       Initial sol. |           Best sol. |
|--------------:|-------------------:|--------------------:|
|    Total Cost |        16158030.18 |          6538344.14 |

What actually happened?

|        Metric |       Initial sol. |           Best sol. |
|--------------:|-------------------:|--------------------:|
|    Total Cost | 16158030.178238558 |    6538344.13613617 |

What versions are you using?

Please include code that reproduces the issue.

    x = prettytable.PrettyTable(float_format="10.2") #same with 10.2f, .2f, .2
    x.field_names = ["Metric", "Initial sol.", "Best sol."]
    x.add_rows([
        ["Total Cost", from_solution.total_cost, to_solution.total_cost],
    ])
hugovk commented 1 year ago

Please can you post a complete, runnable snippet? For example, replace from_solution.total_cost, to_solution.total_cost with example values.

For good tips, see https://stackoverflow.com/help/minimal-reproducible-example

ajgringo619 commented 1 year ago

Try setting the float_format after the rows are added.

andrea-cassioli-maersk commented 1 year ago

@hugovk sorry for replying so late. here some examples

>>> x = prettytable.PrettyTable(float_format="10.2f") #same with 10.2f, .2f, .2
>>> x.field_names = ["Metric", "Initial sol.", "Best sol."]
>>> x.add_rows([["foo", 1.0/3., 1.0/3.]])
>>> x
+--------+--------------------+--------------------+
| Metric |    Initial sol.    |     Best sol.      |
+--------+--------------------+--------------------+
|  foo   | 0.3333333333333333 | 0.3333333333333333 |
+--------+--------------------+--------------------+
>>> x = prettytable.PrettyTable(float_format=".2f") #same with 10.2f, .2f, .2
>>> x.field_names = ["Metric", "Initial sol.", "Best sol."]
>>> x.add_rows([["foo", 1.0/3., 1.0/3.]])
>>> x
+--------+--------------------+--------------------+
| Metric |    Initial sol.    |     Best sol.      |
+--------+--------------------+--------------------+
|  foo   | 0.3333333333333333 | 0.3333333333333333 |
+--------+--------------------+--------------------+
>>> x.add_rows([["foo", 1.0/3., 1.0e5/3.]])
>>> x
+--------+--------------------+--------------------+
| Metric |    Initial sol.    |     Best sol.      |
+--------+--------------------+--------------------+
|  foo   | 0.3333333333333333 | 0.3333333333333333 |
|  foo   | 0.3333333333333333 | 33333.333333333336 |
+--------+--------------------+--------------------+
>>> 

@ajgringo619 it works as you suggested

>>> x.float_format = "10.2f"
>>> x
+--------+--------------+-------------+
| Metric | Initial sol. |  Best sol.  |
+--------+--------------+-------------+
|  foo   |       0.33f  |       0.33f |
|  foo   |       0.33f  |   33333.33f |
+--------+--------------+-------------+

Seems a bug to me.

hugovk commented 1 year ago

Thanks, and as a standalone script:

import prettytable

x = prettytable.PrettyTable(float_format="10.2f")  # same with 10.2f, .2f, .2
x.field_names = ["Metric", "Initial sol.", "Best sol."]
x.add_rows([["foo", 1.0 / 3.0, 1.0 / 3.0]])
print(x)

x = prettytable.PrettyTable()
x.field_names = ["Metric", "Initial sol.", "Best sol."]
x.add_rows([["foo", 1.0 / 3.0, 1.0 / 3.0]])
x.float_format = "10.2f"
print(x)

Looks like the problem is in here, self._field_names is [] so it's not setting any value in the else block:

    @float_format.setter
    def float_format(self, val):
        if val is None or (isinstance(val, dict) and len(val) == 0):
            self._float_format = {}
        else:
            self._validate_option("float_format", val)
            for field in self._field_names:
                self._float_format[field] = val

Called from self.float_format = kwargs["float_format"] or {} in __init__.