8
8
9
9
import numpy as np
10
10
11
- from pandas import isnull
12
- from pandas .tseries .period import Period
11
+ from pandas .tseries .period import Period , PeriodIndex
13
12
from pandas .tseries .offsets import DateOffset
14
13
import pandas .tseries .frequencies as frequencies
15
- from pandas .tseries .index import DatetimeIndex
16
- import pandas .core .common as com
17
14
18
- from pandas .tseries .converter import (PeriodConverter , TimeSeries_DateLocator ,
15
+ from pandas .tseries .converter import (TimeSeries_DateLocator ,
19
16
TimeSeries_DateFormatter )
20
17
21
18
#----------------------------------------------------------------------
22
19
# Plotting functions and monkey patches
23
20
24
21
25
- def tsplot (series , plotf , ** kwargs ):
22
+ def tsplot (series , plotf , ax = None , ** kwargs ):
26
23
"""
27
24
Plots a Series on the given Matplotlib axes or the current axes
28
25
@@ -36,36 +33,21 @@ def tsplot(series, plotf, **kwargs):
36
33
Supports same kwargs as Axes.plot
37
34
38
35
"""
39
- # Used inferred freq is possible, need a test case for inferred
40
- if 'ax' in kwargs :
41
- ax = kwargs .pop ('ax' )
42
- else :
43
- import matplotlib .pyplot as plt
44
- ax = plt .gca ()
45
-
46
- freq = _get_freq (ax , series )
47
- # resample against axes freq if necessary
48
- if freq is None : # pragma: no cover
49
- raise ValueError ('Cannot use dynamic axis without frequency info' )
50
- else :
51
- # Convert DatetimeIndex to PeriodIndex
52
- if isinstance (series .index , DatetimeIndex ):
53
- series = series .to_period (freq = freq )
54
- freq , ax_freq , series = _maybe_resample (series , ax , freq , plotf ,
55
- kwargs )
56
-
36
+ if ax is None :
37
+ raise ValueError ('ax keyword must be passed' )
38
+ if not isinstance (series .index , PeriodIndex ):
39
+ raise ValueError ('Passed data must have PeriodIndex' )
57
40
# Set ax with freq info
58
- _decorate_axes (ax , freq , kwargs )
41
+ _decorate_axes (ax , series . index . freq )
59
42
60
43
# how to make sure ax.clear() flows through?
61
- if not hasattr (ax , '_plot_data' ) :
44
+ if getattr (ax , '_plot_data' , None ) is None :
62
45
ax ._plot_data = []
63
46
ax ._plot_data .append ((series , plotf , kwargs ))
64
47
lines = plotf (ax , series .index ._mpl_repr (), series .values , ** kwargs )
65
48
66
49
# set date formatter, locators and rescale limits
67
50
format_dateaxis (ax , ax .freq )
68
-
69
51
# x and y coord info
70
52
ax .format_coord = lambda t , y : ("t = {0} "
71
53
"y = {1:8f}" .format (Period (ordinal = int (t ),
@@ -75,24 +57,24 @@ def tsplot(series, plotf, **kwargs):
75
57
return lines
76
58
77
59
78
- def _maybe_resample (series , ax , freq , plotf , kwargs ):
60
+ def _maybe_resample (data , ax , freq , kwargs ):
79
61
ax_freq = _get_ax_freq (ax )
80
62
if ax_freq is not None and freq != ax_freq :
81
63
if frequencies .is_superperiod (freq , ax_freq ): # upsample input
82
- series = series .copy ()
83
- series .index = series .index .asfreq (ax_freq , how = 's' )
64
+ data = data .copy ()
65
+ data .index = data .index .asfreq (ax_freq , how = 's' )
84
66
freq = ax_freq
85
67
elif _is_sup (freq , ax_freq ): # one is weekly
86
68
how = kwargs .pop ('how' , 'last' )
87
- series = series .resample ('D' , how = how ).dropna ()
88
- series = series .resample (ax_freq , how = how ).dropna ()
69
+ data = data .resample ('D' , how = how ).dropna ()
70
+ data = data .resample (ax_freq , how = how ).dropna ()
89
71
freq = ax_freq
90
72
elif frequencies .is_subperiod (freq , ax_freq ) or _is_sub (freq , ax_freq ):
91
- _upsample_others (ax , freq , plotf , kwargs )
73
+ _upsample_others (ax , freq )
92
74
ax_freq = freq
93
75
else : # pragma: no cover
94
76
raise ValueError ('Incompatible frequency conversion' )
95
- return freq , ax_freq , series
77
+ return data
96
78
97
79
98
80
def _get_ax_freq (ax ):
@@ -115,67 +97,91 @@ def _is_sup(f1, f2):
115
97
(f2 .startswith ('W' ) and frequencies .is_superperiod (f1 , 'D' )))
116
98
117
99
118
- def _upsample_others (ax , freq , plotf , kwargs ):
119
- legend = ax .get_legend ()
120
- lines , labels = _replot_ax (ax , freq , kwargs )
100
+ def _upsample_others (ax , freq ):
101
+
102
+ def _replot (ax ):
103
+ data = getattr (ax , '_plot_data' , None )
104
+ if data is None :
105
+ return
106
+
107
+ # preserve legend
108
+ leg = ax .get_legend ()
109
+ handles , labels = ax .get_legend_handles_labels ()
110
+
111
+ ax ._plot_data = []
112
+ ax .clear ()
113
+ _decorate_axes (ax , freq )
121
114
122
- other_ax = None
123
- if hasattr (ax , 'left_ax' ):
124
- other_ax = ax .left_ax
125
- if hasattr (ax , 'right_ax' ):
126
- other_ax = ax .right_ax
127
-
128
- if other_ax is not None :
129
- rlines , rlabels = _replot_ax (other_ax , freq , kwargs )
130
- lines .extend (rlines )
131
- labels .extend (rlabels )
132
-
133
- if (legend is not None and kwargs .get ('legend' , True ) and
134
- len (lines ) > 0 ):
135
- title = legend .get_title ().get_text ()
136
- if title == 'None' :
137
- title = None
138
- ax .legend (lines , labels , loc = 'best' , title = title )
139
-
140
-
141
- def _replot_ax (ax , freq , kwargs ):
142
- data = getattr (ax , '_plot_data' , None )
143
- ax ._plot_data = []
144
- ax .clear ()
145
- _decorate_axes (ax , freq , kwargs )
146
-
147
- lines = []
148
- labels = []
149
- if data is not None :
150
115
for series , plotf , kwds in data :
151
116
series = series .copy ()
152
117
idx = series .index .asfreq (freq , how = 'S' )
153
118
series .index = idx
154
- ax ._plot_data .append (series )
155
- lines .append (plotf (ax , series .index ._mpl_repr (), series .values , ** kwds )[0 ])
156
- labels .append (com .pprint_thing (series .name ))
119
+ ax ._plot_data .append ((series , plotf , kwds ))
120
+ plotf (ax , series .index ._mpl_repr (), series , ** kwds )
121
+
122
+ if leg is not None :
123
+ ax .legend (handles , labels , title = leg .get_title ().get_text ())
124
+
125
+ _replot (ax )
126
+ if hasattr (ax , 'left_ax' ):
127
+ _replot (ax .left_ax )
128
+ elif hasattr (ax , 'right_ax' ):
129
+ _replot (ax .right_ax )
130
+
131
+
132
+ def _replot_x_compat (ax ):
133
+
134
+ def _replot (ax ):
135
+ data = getattr (ax , '_plot_data' , None )
136
+ if data is None :
137
+ return
138
+
139
+ # preserve legend
140
+ leg = ax .get_legend ()
141
+ handles , labels = ax .get_legend_handles_labels ()
142
+
143
+ ax ._plot_data = None
144
+ ax .clear ()
145
+
146
+ _decorate_axes (ax , None )
147
+
148
+ for series , plotf , kwds in data :
149
+ idx = series .index .to_timestamp (how = 'e' )
150
+ series .index = idx
151
+ plotf (ax , series .index_mpl_repr (), series , ** kwds )
157
152
158
- return lines , labels
153
+ if leg is not None :
154
+ ax .legend (handles , labels , title = leg .get_title ().get_text ())
155
+
156
+ _replot (ax )
157
+ if hasattr (ax , 'left_ax' ):
158
+ _replot (ax .left_ax )
159
+ elif hasattr (ax , 'right_ax' ):
160
+ _replot (ax .right_ax )
159
161
160
162
161
- def _decorate_axes (ax , freq , kwargs ):
163
+ def _decorate_axes (ax , freq ):
162
164
ax .freq = freq
163
165
xaxis = ax .get_xaxis ()
164
166
xaxis .freq = freq
165
- if not hasattr (ax , 'legendlabels' ):
166
- ax .legendlabels = [kwargs .get ('label' , None )]
167
- else :
168
- ax .legendlabels .append (kwargs .get ('label' , None ))
169
167
ax .view_interval = None
170
168
ax .date_axis_info = None
171
169
172
170
173
- def _get_freq (ax , series ):
174
- # get frequency from data
175
- freq = getattr (series .index , 'freq' , None )
171
+ def _get_index_freq (data ):
172
+ freq = getattr (data .index , 'freq' , None )
176
173
if freq is None :
177
- freq = getattr (series .index , 'inferred_freq' , None )
174
+ freq = getattr (data .index , 'inferred_freq' , None )
175
+ if freq == 'B' :
176
+ weekdays = np .unique (data .index .dayofweek )
177
+ if (5 in weekdays ) or (6 in weekdays ):
178
+ freq = None
179
+ return freq
180
+
178
181
182
+ def _get_freq (ax , data ):
183
+ # get frequency from data
184
+ freq = _get_index_freq (data )
179
185
ax_freq = getattr (ax , 'freq' , None )
180
186
181
187
# use axes freq if no data freq
0 commit comments