ENH: Add the ability to have a separate title for each subplot when plotting #14753

Merged
merged 15 commits into from Dec 9, 2016

Conversation

Projects
None yet
5 participants
Contributor

bmagnusson commented Nov 26, 2016 edited

  • [] tests added / passed
  • [] passes git diff upstream/master | flake8 --diff
  • [] whatsnew entry

bmagnusson added some commits Nov 26, 2016

@bmagnusson bmagnusson Add logic such that if 'title' is a list and 'subplots' is True, use …
…each item of the list as the title of the individual subplots.
3f133ac
@bmagnusson bmagnusson ENH: Add the ability to have a separate title for each subplot when p…
…lotting.
55f4667
@bmagnusson bmagnusson Merge branch 'master' into plotting
8d1b598

codecov-io commented Nov 27, 2016 edited

Current coverage is 85.26% (diff: 0.00%)

Merging #14753 into master will decrease coverage by 0.01%

@@             master     #14753   diff @@
==========================================
  Files           144        144          
  Lines         50968      50977     +9   
  Methods           0          0          
  Messages          0          0          
  Branches          0          0          
==========================================
+ Hits          43466      43467     +1   
- Misses         7502       7510     +8   
  Partials          0          0          

Powered by Codecov. Last update 3ac41ab...59ab880

pandas/tools/plotting.py
@@ -1217,7 +1217,11 @@ def _adorn_subplots(self):
if self.title:
if self.subplots:
- self.fig.suptitle(self.title)
+ if type(self.title) == list:
@sinhrks

sinhrks Nov 27, 2016

Member

pls use is_list_like, and check the input length are correct. Note that all the axes may not require title when you specify layout

@bmagnusson

bmagnusson Nov 28, 2016

Contributor

Ok I'll use is_list_like. I purposely did not check the lengths as a feature. As it's written, if you only provide a list of two strings, but the plot has 3 suplots, the first two subplots will have a title and the third will be left without one.

Member

sinhrks commented Nov 27, 2016

Thx for the PR. can u add tests and release note? Also, pls link the original issue if we have.

bmagnusson added some commits Nov 28, 2016

@bmagnusson bmagnusson switch to using 'is_list_like' ecb9453
@bmagnusson bmagnusson add line describing the new titles for subplots feature d6d1b0c
@bmagnusson bmagnusson add tests to check if the titles above subplots are correct if 'subpl…
…ots' == True and 'title' is a list
94ea2d3
Contributor

bmagnusson commented Nov 28, 2016

I did my best at adding a test and release note. I didn't see an original issue that this addresses. It's just something I have on my local that I wanted to contribute.

pandas/tests/plotting/test_misc.py
+ self.assertEqual([p.title._text for p in plot], title)
+
+ # Case len(title) > len(df)
+ plot = df.plot(subplots=True, title=title + ['Ignore me!'])
@sinhrks

sinhrks Nov 28, 2016

Member

I think we should raise if length of passed list and number of axes are different.

@bmagnusson

bmagnusson Nov 29, 2016

Contributor

Sounds good I added exceptions and pushed. Is ValueError appropriate here?

pandas/tools/plotting.py
+ for (ax, title) in zip(self.axes, self.title):
+ ax.set_title(title)
+ else:
+ self.fig.suptitle(self.title)
else:
self.axes[0].set_title(self.title)
@sinhrks

sinhrks Nov 28, 2016

Member

should raise if subplots=False and input is list-like

@bmagnusson bmagnusson -raise ValueError if len(title) != number of columns.
-raise ValueError if subplots=False and title is of type list
eb43f25
Contributor

bmagnusson commented Dec 3, 2016

Is there anything else I need to do for this change to get pulled in?

pandas/tools/plotting.py
@@ -1217,8 +1217,22 @@ def _adorn_subplots(self):
if self.title:
if self.subplots:
- self.fig.suptitle(self.title)
+ if is_list_like(self.title):
+ if len(self.title) != len(self.axes):
@sinhrks

sinhrks Dec 6, 2016

Member

pls use self.nseries. Number of columns and axes and can differ when layout is specified.

Also add test case with 3 numeric columns df with df.plot(subplots=True, layout=(2, 2))

@bmagnusson

bmagnusson Dec 7, 2016

Contributor

Done :)

Member

sinhrks commented Dec 6, 2016

@TomAugspurger pls have a look when you have a time.

doc/source/whatsnew/v0.20.0.txt
@@ -40,7 +40,7 @@ Other enhancements
^^^^^^^^^^^^^^^^^^
- ``pd.read_excel`` now preserves sheet order when using ``sheetname=None`` (:issue:`9930`)
-
+- ``pd.DataFrame.plot`` now prints a title above each subplot if ``suplots=True`` and ``title`` is a list of strings
@TomAugspurger

TomAugspurger Dec 6, 2016

Contributor

You can add this PR number in the issue tag (:issue:14753)

@bmagnusson

bmagnusson Dec 7, 2016

Contributor

Done :)

pandas/tools/plotting.py
- self.fig.suptitle(self.title)
+ if is_list_like(self.title):
+ if len(self.title) != len(self.axes):
+ msg = 'The length of `title` must equal the number ' \
@TomAugspurger

TomAugspurger Dec 6, 2016

Contributor

It'd be nice to report the length of title and the expected number of columns in the error message.

@bmagnusson

bmagnusson Dec 7, 2016

Contributor

Done :)

bmagnusson added some commits Dec 7, 2016

@bmagnusson bmagnusson added :issue:`14753` 5586a96
@bmagnusson bmagnusson -use self.nseries instead of len(self.axes)
-print out length of title and number of columns in error message
aa5bb98
@bmagnusson bmagnusson -use self.nseries instead of len(self.axes)
-print out length of title and number of columns in error message
-added test case for when layout=(2,2) but number of columns=3
2059339
@bmagnusson bmagnusson Merge remote-tracking branch 'upstream/master' into plotting
# Conflicts:
#	doc/source/whatsnew/v0.20.0.txt
7a293ef
pandas/tests/plotting/test_misc.py
+
+ # Case len(title) == len(df)
+ plot = df.plot(subplots=True, title=title)
+ self.assertEqual([p.title._text for p in plot], title)
@TomAugspurger

TomAugspurger Dec 7, 2016

Contributor

Sorry, I missed this earlier, but can you use p.get_title() instead of the private matplotlib ._text method. Same thing down on line 300, ax.get_title().

@bmagnusson

bmagnusson Dec 7, 2016

Contributor

Oh cool I didn't know that existed! Just pushed with the change.

@sinhrks

sinhrks approved these changes Dec 7, 2016

@bmagnusson bmagnusson use .get_title() instead of .title._text
301cc7d
Contributor

TomAugspurger commented Dec 7, 2016

Great thanks. +1 for merge when travis passes. Just ping us if you notice that it's green before we do

Contributor

bmagnusson commented Dec 7, 2016

All green :)

@jorisvandenbossche

@bmagnusson few more minor (stylistic) comments

pandas/tools/plotting.py
+ msg = 'The length of `title` must equal the number ' \
+ 'of columns if using `title` of type `list` ' \
+ 'and `subplots=True`.\n' \
+ 'length of title = {}\n' \
@jorisvandenbossche

jorisvandenbossche Dec 7, 2016

Owner

Can you use parentheses around the full string instead of \ for the line continuation? (for consistency within the project)

pandas/tools/plotting.py
else:
+ if is_list_like(self.title):
+ msg = 'Using `title` of type `list` is not supported ' \
+ 'unless `subplots=True` is passed'
pandas/tools/plotting.py
- title : string
- Title to use for the plot
+ title : string or list
+ If a string is passed, print the string at the top of the figure. If a
@jorisvandenbossche

jorisvandenbossche Dec 7, 2016

Owner

Can you leave the starting sentence "Title to use for the plot" ?

pandas/tools/plotting.py
- Title to use for the plot
+ title : string or list
+ If a string is passed, print the string at the top of the figure. If a
+ list is passed and subplots is True, print each item in the
@jorisvandenbossche

jorisvandenbossche Dec 7, 2016

Owner

single backticks (`) around 'subplots' (to make it clear that it is a keyword)

@bmagnusson bmagnusson -Add 'Title to use for the plot' as the first sentence for the docstr…
…ing.

-A few other stylistic changes for consistency.
5b88951
Contributor

bmagnusson commented Dec 8, 2016

Huh. I assume there is something funny going on since I didn't change any actual code. Is there a way to restart the checks?

bmagnusson added some commits Dec 8, 2016

@bmagnusson bmagnusson Merge remote-tracking branch 'upstream/master' into plotting
c206daf
@bmagnusson bmagnusson Fix 'continuation line under-indented for visual indent' found by lin…
…ting.
59ab880
Contributor

bmagnusson commented Dec 8, 2016

Ah! I figured it out. I had a linting error (I'll start doing lint before committing oops!)

Contributor

bmagnusson commented Dec 9, 2016

All green now! Anything else to change? If not, thanks for all the help everyone! I had fun. This was my first pull request but it certainly won't be the last :).

jorisvandenbossche added this to the 0.20.0 milestone Dec 9, 2016

@jorisvandenbossche jorisvandenbossche merged commit 5f057cb into pandas-dev:master Dec 9, 2016

2 checks passed

continuous-integration/appveyor/pr AppVeyor build succeeded
Details
continuous-integration/travis-ci/pr The Travis CI build passed
Details

@bmagnusson Thanks! Looking forward to more PRs :-)

@yarikoptic yarikoptic added a commit to neurodebian/pandas that referenced this pull request Dec 12, 2016

@yarikoptic yarikoptic Merge commit 'v0.19.0-174-g81a2f79' into releases
* commit 'v0.19.0-174-g81a2f79': (156 commits)
  BLD: escape GH_TOKEN in build_docs
  TST: Correct results with np.size and crosstab (#4003) (#14755)
  Frame benchmarking sum instead of mean (#14824)
  CLN: lint of test_base.py
  BUG: Allow TZ-aware DatetimeIndex in merge_asof() (#14844)
  BUG: GH11847 Unstack with mixed dtypes coerces everything to object
  TST: skip testing on windows for specific formatting which sometimes hangs (#14851)
  BLD: try new gh token for pandas-docs
  CLN/PERF: clean-up of the benchmarks (#14099)
  ENH: add timedelta as valid type for interpolate with method='time' (#14799)
  DOC: add section on groupby().rolling/expanding/resample (#14801)
  TST: add test to confirm GH14606 (specify category dtype for empty) (#14752)
  BLD: use org name in build-docs.sh
  BF(TST): use = (native) instead of < (little endian) for target data types (#14832)
  ENH: Introduce UnsortedIndexError  GH11897 (#14762)
  ENH: Add the ability to have a separate title for each subplot when plotting (#14753)
  DOC: Fix grammar and formatting typos (#14803)
  BLD: try new build credentials for pandas-docs
  TST: Test pivot with categorical data
  MAINT: Cleanup pandas/src/parser (#14740)
  ...
6c87601

@yarikoptic yarikoptic added a commit to neurodebian/pandas that referenced this pull request Dec 12, 2016

@yarikoptic yarikoptic Merge branch 'releases' (as of v0.19.0-174-g81a2f79) into debian
release 0.19.1 was from release branch

* releases: (156 commits)
  BLD: escape GH_TOKEN in build_docs
  TST: Correct results with np.size and crosstab (#4003) (#14755)
  Frame benchmarking sum instead of mean (#14824)
  CLN: lint of test_base.py
  BUG: Allow TZ-aware DatetimeIndex in merge_asof() (#14844)
  BUG: GH11847 Unstack with mixed dtypes coerces everything to object
  TST: skip testing on windows for specific formatting which sometimes hangs (#14851)
  BLD: try new gh token for pandas-docs
  CLN/PERF: clean-up of the benchmarks (#14099)
  ENH: add timedelta as valid type for interpolate with method='time' (#14799)
  DOC: add section on groupby().rolling/expanding/resample (#14801)
  TST: add test to confirm GH14606 (specify category dtype for empty) (#14752)
  BLD: use org name in build-docs.sh
  BF(TST): use = (native) instead of < (little endian) for target data types (#14832)
  ENH: Introduce UnsortedIndexError  GH11897 (#14762)
  ENH: Add the ability to have a separate title for each subplot when plotting (#14753)
  DOC: Fix grammar and formatting typos (#14803)
  BLD: try new build credentials for pandas-docs
  TST: Test pivot with categorical data
  MAINT: Cleanup pandas/src/parser (#14740)
  ...
dd7e977

@ischurov ischurov added a commit to ischurov/pandas that referenced this pull request Dec 19, 2016

@bmagnusson @ischurov bmagnusson + ischurov ENH: Add the ability to have a separate title for each subplot when p…
…lotting (#14753)

* Add logic such that if 'title' is a list and 'subplots' is True, use each item of the list as the title of the individual subplots.
bd59882
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment