Skip to content

Commit 25d5299

Browse files
s-weigandTomAugspurger
authored andcommitted
BUG: Plotting Timedelta on y-axis #16953 (#17430)
* implemented fix for GH issue #16953 * added tests for fix of issue #16953 * changed comments for git issue to pandas style GH# * changed linelength in tests, so all lines are less than 80 characters * added whatsnew entry * swaped conversion and filtering of values, for plot to also work with object dtypes * refomated code, so len(line) < 80 * changed whatsnew with timedelta and datetime dtypes * added support for datetimetz and extended tests * added reason to pytest.mark.xfail
1 parent 5bca6ce commit 25d5299

File tree

3 files changed

+84
-2
lines changed

3 files changed

+84
-2
lines changed

Diff for: doc/source/whatsnew/v0.21.0.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,7 @@ I/O
432432
Plotting
433433
^^^^^^^^
434434
- Bug in plotting methods using ``secondary_y`` and ``fontsize`` not setting secondary axis font size (:issue:`12565`)
435-
435+
- Bug when plotting ``timedelta`` and ``datetime`` dtypes on y-axis (:issue:`16953`)
436436

437437
Groupby/Resample/Rolling
438438
^^^^^^^^^^^^^^^^^^^^^^^^

Diff for: pandas/plotting/_core.py

+7-1
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,13 @@ def _compute_plot_data(self):
342342
label = 'None'
343343
data = data.to_frame(name=label)
344344

345-
numeric_data = data._convert(datetime=True)._get_numeric_data()
345+
# GH16953, _convert is needed as fallback, for ``Series``
346+
# with ``dtype == object``
347+
data = data._convert(datetime=True, timedelta=True)
348+
numeric_data = data.select_dtypes(include=[np.number,
349+
"datetime",
350+
"datetimetz",
351+
"timedelta"])
346352

347353
try:
348354
is_empty = numeric_data.empty

Diff for: pandas/tests/plotting/test_frame.py

+76
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,82 @@ def test_subplots_timeseries(self):
380380
self._check_ticks_props(ax, xlabelsize=7, xrot=45,
381381
ylabelsize=7)
382382

383+
def test_subplots_timeseries_y_axis(self):
384+
# GH16953
385+
data = {"numeric": np.array([1, 2, 5]),
386+
"timedelta": [pd.Timedelta(-10, unit="s"),
387+
pd.Timedelta(10, unit="m"),
388+
pd.Timedelta(10, unit="h")],
389+
"datetime_no_tz": [pd.to_datetime("2017-08-01 00:00:00"),
390+
pd.to_datetime("2017-08-01 02:00:00"),
391+
pd.to_datetime("2017-08-02 00:00:00")],
392+
"datetime_all_tz": [pd.to_datetime("2017-08-01 00:00:00",
393+
utc=True),
394+
pd.to_datetime("2017-08-01 02:00:00",
395+
utc=True),
396+
pd.to_datetime("2017-08-02 00:00:00",
397+
utc=True)],
398+
"text": ["This", "should", "fail"]}
399+
testdata = DataFrame(data)
400+
401+
ax_numeric = testdata.plot(y="numeric")
402+
assert (ax_numeric.get_lines()[0].get_data()[1] ==
403+
testdata["numeric"].values).all()
404+
ax_timedelta = testdata.plot(y="timedelta")
405+
assert (ax_timedelta.get_lines()[0].get_data()[1] ==
406+
testdata["timedelta"].values).all()
407+
ax_datetime_no_tz = testdata.plot(y="datetime_no_tz")
408+
assert (ax_datetime_no_tz.get_lines()[0].get_data()[1] ==
409+
testdata["datetime_no_tz"].values).all()
410+
ax_datetime_all_tz = testdata.plot(y="datetime_all_tz")
411+
assert (ax_datetime_all_tz.get_lines()[0].get_data()[1] ==
412+
testdata["datetime_all_tz"].values).all()
413+
with pytest.raises(TypeError):
414+
testdata.plot(y="text")
415+
416+
@pytest.mark.xfail(reason='not support for period, categorical, '
417+
'datetime_mixed_tz')
418+
def test_subplots_timeseries_y_axis_not_supported(self):
419+
"""
420+
This test will fail for:
421+
period:
422+
since period isn't yet implemented in ``select_dtypes``
423+
and because it will need a custom value converter +
424+
tick formater (as was done for x-axis plots)
425+
426+
categorical:
427+
because it will need a custom value converter +
428+
tick formater (also doesn't work for x-axis, as of now)
429+
430+
datetime_mixed_tz:
431+
because of the way how pandas handels ``Series`` of
432+
``datetime`` objects with different timezone,
433+
generally converting ``datetime`` objects in a tz-aware
434+
form could help with this problem
435+
"""
436+
data = {"numeric": np.array([1, 2, 5]),
437+
"period": [pd.Period('2017-08-01 00:00:00', freq='H'),
438+
pd.Period('2017-08-01 02:00', freq='H'),
439+
pd.Period('2017-08-02 00:00:00', freq='H')],
440+
"categorical": pd.Categorical(["c", "b", "a"],
441+
categories=["a", "b", "c"],
442+
ordered=False),
443+
"datetime_mixed_tz": [pd.to_datetime("2017-08-01 00:00:00",
444+
utc=True),
445+
pd.to_datetime("2017-08-01 02:00:00"),
446+
pd.to_datetime("2017-08-02 00:00:00")]}
447+
testdata = pd.DataFrame(data)
448+
ax_period = testdata.plot(x="numeric", y="period")
449+
assert (ax_period.get_lines()[0].get_data()[1] ==
450+
testdata["period"].values).all()
451+
ax_categorical = testdata.plot(x="numeric", y="categorical")
452+
assert (ax_categorical.get_lines()[0].get_data()[1] ==
453+
testdata["categorical"].values).all()
454+
ax_datetime_mixed_tz = testdata.plot(x="numeric",
455+
y="datetime_mixed_tz")
456+
assert (ax_datetime_mixed_tz.get_lines()[0].get_data()[1] ==
457+
testdata["datetime_mixed_tz"].values).all()
458+
383459
@pytest.mark.slow
384460
def test_subplots_layout(self):
385461
# GH 6667

0 commit comments

Comments
 (0)