Join GitHub today
GitHub is home to over 20 million developers working together to host and review code, manage projects, and build software together.
ENH: Added a `PercentFormatter` class to `matplotlib.ticker` #6251
Conversation
mdboom
added the
needs_review
label
Mar 30, 2016
|
@mdboom While I realize that you have a script to do this, it is really disconcerting to see your name pop up fractions of a second after I create a PR :) |
efiring
commented on an outdated diff
Mar 30, 2016
| @@ -914,6 +1009,17 @@ class EngFormatter(Formatter): | ||
| } | ||
| def __init__(self, unit="", places=None): | ||
| + """ | ||
| + Initializes an engineering notation formatter. | ||
| + | ||
| + `unit` is a string containing the abbreviated name of the unit, | ||
| + suitable for use with single-letter representations of powers of | ||
| + 1000. For example, 'Hz' or 'm'. | ||
| + | ||
| + `places` is the percision with which to display the number, |
|
|
efiring
commented on an outdated diff
Mar 30, 2016
efiring
commented on an outdated diff
Mar 30, 2016
| @@ -973,6 +1078,87 @@ def format_eng(self, num): | ||
| return formatted.strip() | ||
| +class PercentFormatter(Formatter): | ||
| + """ | ||
| + Format numbers as a percentage. | ||
| + | ||
| + How the number is converted into a percentage is determined by the | ||
| + `mx` parameter. `mx` is the data value that corresponds to 100%. | ||
| + Percentages are computed as ``x / mx * 100``. So if the data is | ||
| + already scaled to be percentages, `mx` will be 100. Another common | ||
| + situation is where `max` is 1.0. | ||
| + """ | ||
| + def __init__(self, mx=100, decimals=None, symbol='%'): | ||
| + """ | ||
| + Initializes the formatter. | ||
| + | ||
| + `max` is the data value that corresponds to 100%. `symbol` is |
efiring
Owner
|
|
I am not familiar enough with Python 2.7 to immediately understand why the following is not working:
Are nested formats not allowed? |
efiring
and 1 other
commented on an outdated diff
Mar 30, 2016
| @@ -973,6 +1078,87 @@ def format_eng(self, num): | ||
| return formatted.strip() | ||
| +class PercentFormatter(Formatter): | ||
| + """ | ||
| + Format numbers as a percentage. | ||
| + | ||
| + How the number is converted into a percentage is determined by the | ||
| + `mx` parameter. `mx` is the data value that corresponds to 100%. | ||
| + Percentages are computed as ``x / mx * 100``. So if the data is | ||
| + already scaled to be percentages, `mx` will be 100. Another common | ||
| + situation is where `max` is 1.0. | ||
| + """ | ||
| + def __init__(self, mx=100, decimals=None, symbol='%'): |
efiring
Owner
|
efiring
and 1 other
commented on an outdated diff
Mar 30, 2016
| + d = self.convert_to_pct(d) # d is a difference, so this works fine | ||
| + decimals = math.ceil(2.0 - math.log10(2.0 * d)) | ||
| + if decimals > 5: | ||
| + decimals = 5 | ||
| + elif decimals < 0: | ||
| + decimals = 0 | ||
| + else: | ||
| + decimals = self.decimals | ||
| + s = '{x:0.{decimals}f}'.format(x=x, decimals=decimals) | ||
| + | ||
| + if self.symbol: | ||
| + return s + self.symbol | ||
| + return s | ||
| + | ||
| + def convert_to_pct(self, x): | ||
| + return x / self.max * 100.0 |
efiring
Owner
|
|
There are so many cleanup changes here that I recommend breaking this into two PRs: one for the cleanups, and a second one for the new feature. |
|
No problem with that. Is there an easy way to do that without closing this PR? |
efiring
commented on an outdated diff
Mar 30, 2016
| @@ -1016,7 +1016,7 @@ def __init__(self, unit="", places=None): | ||
| suitable for use with single-letter representations of powers of | ||
| 1000. For example, 'Hz' or 'm'. | ||
| - `places` is the percision with which to display the number, | ||
| + `places` is the prrcision with which to display the number, |
|
|
That's https://waffle.io/
Create a new branch starting on this one, rebase it to include only cleanup, and open a new PR for it. When that's merged, rebase this one on top of master and drop all the cleanup from here. |
|
I think you would make a separate branch on your repo for the cleanups, and make a PR from that. Then, on your pctFormatter branch, isolate the PercentFormatter part with additional commits, and use 'git rebase -i' to squash it down to a single commit. Force-push that to your github repo, and it will replace the present commits in the present PR. |
madphysicist
referenced
this pull request
Mar 31, 2016
Merged
MAINT: Updates to formatters in `matplotlib.ticker` #6253
|
I did the split (#6253) and fixed the Py2.7 error. Turns out Py3 automatically converts acceptable format precisions into an int. Py2 does not. The only potentially unrelated change I kept here was moving |
madphysicist
changed the title from
Added a PercentFormatter class to `matplotlib.ticker` to ENH: Added a PercentFormatter class to `matplotlib.ticker`
Mar 31, 2016
madphysicist
changed the title from
ENH: Added a PercentFormatter class to `matplotlib.ticker` to ENH: Added a `PercentFormatter` class to `matplotlib.ticker`
Mar 31, 2016
|
Metabolized the docs of |
|
I think that this PR is complete (ready for further review). Same goes for #6253. The failure in Appveyor is the sporadic image comparison failure. It is not related to the code I added as far as I can tell. |
|
Squawk. |
tacaswell
added this to the
2.1 (next point release)
milestone
Apr 7, 2016
|
Cc: @efiring. |
|
In reading the new code, I find that I waste a lot of time trying to figure out what |
madphysicist
added a commit
to madphysicist/matplotlib
that referenced
this pull request
Apr 8, 2016
|
|
madphysicist |
5161407
|
|
I changed On a side-note, I got |
efiring
commented on an outdated diff
Apr 8, 2016
| + (100, 1, '%', 70.23, 50, '70.2%'), | ||
| + # 60.554 instead of 60.55: see https://bugs.python.org/issue5118 | ||
| + (100, 1, '%', 60.554, 40, '60.6%'), | ||
| + # Check auto decimals over different intervals and values | ||
| + (100, None, '%', 95, 1, '95.00%'), | ||
| + (1.0, None, '%', 3, 6, '300%'), | ||
| + (17.0, None, '%', 1, 8.5, '6%'), | ||
| + (17.0, None, '%', 1, 8.4, '5.9%'), | ||
| + (5, None, '%', -100, 0.000001, '-2000.00000%'), | ||
| + # Check percent symbol | ||
| + (1.0, 2, None, 1.2, 100, '120.00'), | ||
| + (75, 3, '', 50, 100, '66.667'), | ||
| + (42, None, '^^Foobar$$', 21, 12, '50.0^^Foobar$$'), | ||
| + ) | ||
| + for xmax, decimals, symbol, x, display_range, expected in test_cases: | ||
| + yield _percent_format_helper, xmax, decimals, symbol, x, display_range, expected |
efiring
Owner
|
|
In addition to the pep-8 failure noted above there is a real failure that I have not tracked down (probably you will spot it instantly). Once those are taken care of, I think this will be functionally ready. It's a nice contribution. You could neaten it up by rebasing to squash the commits. |
|
I went with
and also fixed the other stupid typo. Will push with squash soon. |
|
And now I know why I should have listened the first time. |
|
I don't think the Travis failure is related to my code. |
efiring
merged commit c03262a
into matplotlib:master
Apr 8, 2016
efiring
removed the
needs_review
label
Apr 8, 2016
|
Thank you, @madphysicist! |
madphysicist
deleted the
madphysicist:pctFormatter branch
Apr 8, 2016
|
No problem. Thanks for looking over and accepting my PR! |
madphysicist commentedMar 30, 2016
This is suitable for formatting axes labels as percentages. It has some nice features like being able to convert from arbitrary data scales to percents, a customizable percent symbol and either automatic or manual control over the decimal points.
The original motivation came from my own work as well as these two Stack Overflow questions: