Skip to content

Commit e4975f2

Browse files
committed
BUG/CLN: Repeated time-series plot may raise TypeError
1 parent 2b6bd97 commit e4975f2

File tree

3 files changed

+75
-66
lines changed

3 files changed

+75
-66
lines changed

doc/source/whatsnew/v0.16.1.txt

+1
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ Bug Fixes
108108
- Bug in plotting continuously using ``secondary_y`` may not show legend properly. (:issue:`9610`, :issue:`9779`)
109109

110110
- Bug in ``DataFrame.plot(kind="hist")`` results in ``TypeError`` when ``DataFrame`` contains non-numeric columns (:issue:`9853`)
111+
- Bug in continuous ``DataFrame`` with ``DatatimeIndex`` plot may raise ``TypeError`` (:issue:`9852`)
111112

112113
- Bug in ``Series.quantile`` on empty Series of type ``Datetime`` or ``Timedelta`` (:issue:`9675`)
113114
- Bug in ``where`` causing incorrect results when upcasting was required (:issue:`9731`)

pandas/tools/plotting.py

+42-66
Original file line numberDiff line numberDiff line change
@@ -885,28 +885,16 @@ def _iter_data(self, data=None, keep_index=False, fillna=None):
885885
if fillna is not None:
886886
data = data.fillna(fillna)
887887

888-
from pandas.core.frame import DataFrame
889-
if isinstance(data, (Series, np.ndarray, Index)):
890-
label = self.label if self.label is not None else data.name
888+
if self.sort_columns:
889+
columns = com._try_sort(data.columns)
890+
else:
891+
columns = data.columns
892+
893+
for col in columns:
891894
if keep_index is True:
892-
yield label, data
895+
yield col, data[col]
893896
else:
894-
yield label, np.asarray(data)
895-
elif isinstance(data, DataFrame):
896-
if self.sort_columns:
897-
columns = com._try_sort(data.columns)
898-
else:
899-
columns = data.columns
900-
901-
for col in columns:
902-
# # is this right?
903-
# empty = df[col].count() == 0
904-
# values = df[col].values if not empty else np.zeros(len(df))
905-
906-
if keep_index is True:
907-
yield col, data[col]
908-
else:
909-
yield col, data[col].values
897+
yield col, data[col].values
910898

911899
@property
912900
def nseries(self):
@@ -1006,7 +994,15 @@ def result(self):
1006994
return self.axes[0]
1007995

1008996
def _compute_plot_data(self):
1009-
numeric_data = self.data.convert_objects()._get_numeric_data()
997+
data = self.data
998+
999+
if isinstance(data, Series):
1000+
label = self.kwds.pop('label', None)
1001+
if label is None and data.name is None:
1002+
label = 'None'
1003+
data = data.to_frame(name=label)
1004+
1005+
numeric_data = data.convert_objects()._get_numeric_data()
10101006

10111007
try:
10121008
is_empty = numeric_data.empty
@@ -1027,12 +1023,7 @@ def _add_table(self):
10271023
if self.table is False:
10281024
return
10291025
elif self.table is True:
1030-
from pandas.core.frame import DataFrame
1031-
if isinstance(self.data, Series):
1032-
data = DataFrame(self.data, columns=[self.data.name])
1033-
elif isinstance(self.data, DataFrame):
1034-
data = self.data
1035-
data = data.transpose()
1026+
data = self.data.transpose()
10361027
else:
10371028
data = self.table
10381029
ax = self._get_ax(0)
@@ -1099,18 +1090,15 @@ def _apply_axis_properties(self, axis, rot=None, fontsize=None):
10991090

11001091
@property
11011092
def legend_title(self):
1102-
if hasattr(self.data, 'columns'):
1103-
if not isinstance(self.data.columns, MultiIndex):
1104-
name = self.data.columns.name
1105-
if name is not None:
1106-
name = com.pprint_thing(name)
1107-
return name
1108-
else:
1109-
stringified = map(com.pprint_thing,
1110-
self.data.columns.names)
1111-
return ','.join(stringified)
1093+
if not isinstance(self.data.columns, MultiIndex):
1094+
name = self.data.columns.name
1095+
if name is not None:
1096+
name = com.pprint_thing(name)
1097+
return name
11121098
else:
1113-
return None
1099+
stringified = map(com.pprint_thing,
1100+
self.data.columns.names)
1101+
return ','.join(stringified)
11141102

11151103
def _add_legend_handle(self, handle, label, index=None):
11161104
if not label is None:
@@ -1256,12 +1244,10 @@ def _get_ax(self, i):
12561244
return ax
12571245

12581246
def on_right(self, i):
1259-
from pandas.core.frame import DataFrame
12601247
if isinstance(self.secondary_y, bool):
12611248
return self.secondary_y
12621249

1263-
if (isinstance(self.data, DataFrame) and
1264-
isinstance(self.secondary_y, (tuple, list, np.ndarray, Index))):
1250+
if isinstance(self.secondary_y, (tuple, list, np.ndarray, Index)):
12651251
return self.data.columns[i] in self.secondary_y
12661252

12671253
def _get_style(self, i, col_name):
@@ -1553,16 +1539,14 @@ def __init__(self, data, **kwargs):
15531539
self.x_compat = bool(self.kwds.pop('x_compat'))
15541540

15551541
def _index_freq(self):
1556-
from pandas.core.frame import DataFrame
1557-
if isinstance(self.data, (Series, DataFrame)):
1558-
freq = getattr(self.data.index, 'freq', None)
1559-
if freq is None:
1560-
freq = getattr(self.data.index, 'inferred_freq', None)
1561-
if freq == 'B':
1562-
weekdays = np.unique(self.data.index.dayofweek)
1563-
if (5 in weekdays) or (6 in weekdays):
1564-
freq = None
1565-
return freq
1542+
freq = getattr(self.data.index, 'freq', None)
1543+
if freq is None:
1544+
freq = getattr(self.data.index, 'inferred_freq', None)
1545+
if freq == 'B':
1546+
weekdays = np.unique(self.data.index.dayofweek)
1547+
if (5 in weekdays) or (6 in weekdays):
1548+
freq = None
1549+
return freq
15661550

15671551
def _is_dynamic_freq(self, freq):
15681552
if isinstance(freq, DateOffset):
@@ -1574,9 +1558,7 @@ def _is_dynamic_freq(self, freq):
15741558

15751559
def _no_base(self, freq):
15761560
# hack this for 0.10.1, creating more technical debt...sigh
1577-
from pandas.core.frame import DataFrame
1578-
if (isinstance(self.data, (Series, DataFrame))
1579-
and isinstance(self.data.index, DatetimeIndex)):
1561+
if isinstance(self.data.index, DatetimeIndex):
15801562
base = frequencies.get_freq(freq)
15811563
x = self.data.index
15821564
if (base <= frequencies.FreqGroup.FR_DAY):
@@ -1686,28 +1668,24 @@ def _update_prior(self, y):
16861668
def _maybe_convert_index(self, data):
16871669
# tsplot converts automatically, but don't want to convert index
16881670
# over and over for DataFrames
1689-
from pandas.core.frame import DataFrame
1690-
if (isinstance(data.index, DatetimeIndex) and
1691-
isinstance(data, DataFrame)):
1671+
if isinstance(data.index, DatetimeIndex):
16921672
freq = getattr(data.index, 'freq', None)
16931673

16941674
if freq is None:
16951675
freq = getattr(data.index, 'inferred_freq', None)
16961676
if isinstance(freq, DateOffset):
16971677
freq = freq.rule_code
1698-
freq = frequencies.get_base_alias(freq)
1699-
freq = frequencies.get_period_alias(freq)
17001678

17011679
if freq is None:
17021680
ax = self._get_ax(0)
17031681
freq = getattr(ax, 'freq', None)
17041682

1683+
freq = frequencies.get_base_alias(freq)
1684+
freq = frequencies.get_period_alias(freq)
1685+
17051686
if freq is None:
17061687
raise ValueError('Could not get frequency alias for plotting')
1707-
1708-
data = DataFrame(data.values,
1709-
index=data.index.to_period(freq=freq),
1710-
columns=data.columns)
1688+
data.index = data.index.to_period(freq=freq)
17111689
return data
17121690

17131691
def _post_plot_logic(self):
@@ -2522,9 +2500,7 @@ def plot_series(data, kind='line', ax=None, # Series unique
25222500
if ax is None and len(plt.get_fignums()) > 0:
25232501
ax = _gca()
25242502
ax = getattr(ax, 'left_ax', ax)
2525-
# is there harm in this?
2526-
if label is None:
2527-
label = data.name
2503+
25282504
return _plot(data, kind=kind, ax=ax,
25292505
figsize=figsize, use_index=use_index, title=title,
25302506
grid=grid, legend=legend,

pandas/tseries/tests/test_plotting.py

+32
Original file line numberDiff line numberDiff line change
@@ -636,6 +636,38 @@ def test_mixed_freq_irregular_first(self):
636636
x2 = lines[1].get_xdata()
637637
assert_array_equal(x2, s1.index.asobject.values)
638638

639+
def test_mixed_freq_regular_first_df(self):
640+
# GH 9852
641+
import matplotlib.pyplot as plt
642+
s1 = tm.makeTimeSeries().to_frame()
643+
s2 = s1.iloc[[0, 5, 10, 11, 12, 13, 14, 15], :]
644+
ax = s1.plot()
645+
ax2 = s2.plot(style='g', ax=ax)
646+
lines = ax2.get_lines()
647+
idx1 = PeriodIndex(lines[0].get_xdata())
648+
idx2 = PeriodIndex(lines[1].get_xdata())
649+
self.assertTrue(idx1.equals(s1.index.to_period('B')))
650+
self.assertTrue(idx2.equals(s2.index.to_period('B')))
651+
left, right = ax2.get_xlim()
652+
pidx = s1.index.to_period()
653+
self.assertEqual(left, pidx[0].ordinal)
654+
self.assertEqual(right, pidx[-1].ordinal)
655+
656+
@slow
657+
def test_mixed_freq_irregular_first_df(self):
658+
# GH 9852
659+
import matplotlib.pyplot as plt
660+
s1 = tm.makeTimeSeries().to_frame()
661+
s2 = s1.iloc[[0, 5, 10, 11, 12, 13, 14, 15], :]
662+
ax = s2.plot(style='g')
663+
ax = s1.plot(ax=ax)
664+
self.assertFalse(hasattr(ax, 'freq'))
665+
lines = ax.get_lines()
666+
x1 = lines[0].get_xdata()
667+
assert_array_equal(x1, s2.index.asobject.values)
668+
x2 = lines[1].get_xdata()
669+
assert_array_equal(x2, s1.index.asobject.values)
670+
639671
def test_mixed_freq_hf_first(self):
640672
idxh = date_range('1/1/1999', periods=365, freq='D')
641673
idxl = date_range('1/1/1999', periods=12, freq='M')

0 commit comments

Comments
 (0)