@@ -66,27 +66,30 @@ def tsplot(axes, series, *args, **kwargs):
66
66
Supports same args and kwargs as Axes.plot
67
67
68
68
"""
69
+ # Used inferred freq is possible, need a test case for inferred
69
70
freq = getattr (series .index , 'freq' , None )
70
71
if freq is None and hasattr (series .index , 'inferred_freq' ):
71
72
freq = series .index .inferred_freq
72
73
if isinstance (freq , DateOffset ):
73
74
freq = freq .rule_code
74
75
76
+ # Convert DatetimeIndex to PeriodIndex
75
77
if isinstance (series .index , DatetimeIndex ):
76
78
idx = series .index .to_period (freq = freq )
77
- series = Series (series .values , idx , series .name )
79
+ series = Series (series .values , idx , name = series .name )
78
80
79
81
if not isinstance (series .index , PeriodIndex ):
80
82
raise TypeError ('series argument to tsplot must have DatetimeIndex or '
81
83
'PeriodIndex' )
82
84
83
- args = _check_plot_params (series , series .index , freq , * args )
84
-
85
+ # Specialized ts plotting attributes for Axes
85
86
axes .freq = freq
86
87
axes .legendlabels = [kwargs .get ('label' , None )]
87
88
axes .view_interval = None
88
89
axes .date_axis_info = None
89
90
91
+ # format args and lot
92
+ args = _check_plot_params (series , series .index , freq , * args )
90
93
plotted = axes .plot (* args , ** kwargs )
91
94
92
95
format_dateaxis (axes , axes .freq )
@@ -118,124 +121,110 @@ def get_datevalue(date, freq):
118
121
return None
119
122
raise ValueError ("Unrecognizable date '%s'" % date )
120
123
121
- def format_dateaxis (subplot , freq ):
122
- """
123
- Pretty-formats the date axis (x-axis).
124
124
125
- Major and minor ticks are automatically set for the frequency of the
126
- current underlying series. As the dynamic mode is activated by
127
- default, changing the limits of the x axis will intelligently change
128
- the positions of the ticks.
129
- """
130
- majlocator = TimeSeries_DateLocator (freq , dynamic_mode = True ,
131
- minor_locator = False ,
132
- plot_obj = subplot )
133
- minlocator = TimeSeries_DateLocator (freq , dynamic_mode = True ,
134
- minor_locator = True ,
135
- plot_obj = subplot )
136
- subplot .xaxis .set_major_locator (majlocator )
137
- subplot .xaxis .set_minor_locator (minlocator )
138
-
139
- majformatter = TimeSeries_DateFormatter (freq , dynamic_mode = True ,
140
- minor_locator = False ,
141
- plot_obj = subplot )
142
- minformatter = TimeSeries_DateFormatter (freq , dynamic_mode = True ,
143
- minor_locator = True ,
144
- plot_obj = subplot )
145
- subplot .xaxis .set_major_formatter (majformatter )
146
- subplot .xaxis .set_minor_formatter (minformatter )
147
- pylab .draw_if_interactive ()
125
+ # Check and format plotting parameters
148
126
149
127
def _check_plot_params (series , xdata , freq , * args ):
150
128
"""
151
129
Defines the plot coordinates (and basic plotting arguments).
152
130
"""
153
- # TODO clean up this massive method
154
131
remaining = list (args )
155
132
noinfo_msg = "No date information available!"
133
+
156
134
# No args ? Use defaults, if any
157
135
if len (args ) == 0 :
158
136
if xdata is None :
159
137
raise ValueError (noinfo_msg )
160
138
return (xdata , series )
139
+
161
140
output = []
162
141
while len (remaining ) > 0 :
163
142
a = remaining .pop (0 )
143
+ output .extend (_handle_param (a , remaining , series , xdata , freq ))
164
144
165
- # The argument is a format: use default dates/
166
- if isinstance (a , str ):
167
- if xdata is None :
168
- raise ValueError (noinfo_msg )
169
- else :
170
- output .extend ([xdata , series , a ])
171
-
172
- # The argument is a Series: use its dates for x
173
- elif isinstance (a , Series ):
174
- (x , y ) = (a .index , a .values )
175
- if len (remaining ) > 0 and isinstance (remaining [0 ], str ):
176
- b = remaining .pop (0 )
177
- output .extend ([x , y , b ])
178
- else :
179
- output .extend ([x , y ])
180
-
181
- # The argument is a PeriodIndex............
182
- elif isinstance (a , PeriodIndex ):
183
- # Force to current freq
184
- if freq is not None :
185
- if a .freq != freq :
186
- a = a .asfreq (freq )
187
-
188
- # There's an argument after
189
- if len (remaining ) > 0 :
190
-
191
- #...and it's a format string
192
- if isinstance (remaining [0 ], str ):
193
- b = remaining .pop (0 )
194
- if series is None :
195
- raise ValueError (noinfo_msg )
196
- else :
197
- output .extend ([a , series , b ])
198
-
199
- #... and it's another date: use the default
200
- elif isinstance (remaining [0 ], PeriodIndex ):
201
- if series is None :
202
- raise ValueError (noinfo_msg )
203
- else :
204
- output .extend ([a , series ])
205
-
206
- #... and it must be some data
207
- else :
208
- b = remaining .pop (0 )
209
- if len (remaining ) > 0 :
210
- if isinstance (remaining [0 ], str ):
211
- c = remaining .pop (0 )
212
- output .extend ([a , b , c ])
213
- else :
214
- output .extend ([a , b ])
215
- else :
216
- if series is None :
217
- raise ValueError (noinfo_msg )
218
-
219
- # Otherwise..............................
220
- elif len (remaining ) > 0 and isinstance (remaining [0 ], str ):
221
- b = remaining .pop (0 )
222
- if xdata is None :
223
- raise ValueError (noinfo_msg )
224
- else :
225
- output .extend ([xdata , a , b ])
226
- elif xdata is None :
227
- raise ValueError (noinfo_msg )
228
- else :
229
- output .extend ([xdata , a ])
230
145
# Reinitialize the plot if needed ...........
231
146
if xdata is None :
232
147
xdata = output [0 ]
148
+
233
149
# Force the xdata to the current frequency
234
150
elif output [0 ].freq != freq :
235
151
output = list (output )
236
152
output [0 ] = output [0 ].asfreq (freq )
153
+
237
154
return output
238
155
156
+ def _handle_param (curr , remaining , series , xdata , freq ):
157
+ # The argument is a format: use default dates/
158
+ noinfo_msg = "No date information available!"
159
+ if isinstance (curr , str ):
160
+ if xdata is None :
161
+ raise ValueError (noinfo_msg )
162
+ else :
163
+ return [xdata , series , curr ]
164
+
165
+ # The argument is a Series: use its dates for x
166
+ elif isinstance (curr , Series ):
167
+ (x , y ) = (curr .index , curr .values )
168
+ if len (remaining ) > 0 and isinstance (remaining [0 ], str ):
169
+ b = remaining .pop (0 )
170
+ return [x , y , b ]
171
+ else :
172
+ return [x , y ]
173
+
174
+ # The argument is a PeriodIndex............
175
+ elif isinstance (curr , PeriodIndex ):
176
+ return _handle_period_index (curr , remaining , series , xdata , freq )
177
+
178
+ # Otherwise..............................
179
+ elif len (remaining ) > 0 and isinstance (remaining [0 ], str ):
180
+ b = remaining .pop (0 )
181
+ if xdata is None :
182
+ raise ValueError (noinfo_msg )
183
+ else :
184
+ return [xdata , curr , b ]
185
+ elif xdata is None :
186
+ raise ValueError (noinfo_msg )
187
+ else :
188
+ return [xdata , curr ]
189
+
190
+ def _handle_period_index (curr , remaining , series , xdata , freq ):
191
+ # Force to current freq
192
+ noinfo_msg = "No date information available!"
193
+ if freq is not None :
194
+ if curr .freq != freq :
195
+ curr = curr .asfreq (freq )
196
+
197
+ # There's an argument after
198
+ if len (remaining ) > 0 :
199
+ #...and it's a format string
200
+ if isinstance (remaining [0 ], str ):
201
+ b = remaining .pop (0 )
202
+ if series is None :
203
+ raise ValueError (noinfo_msg )
204
+ else :
205
+ return [curr , series , b ]
206
+
207
+ #... and it's another date: use the default
208
+ elif isinstance (remaining [0 ], PeriodIndex ):
209
+ if series is None :
210
+ raise ValueError (noinfo_msg )
211
+ else :
212
+ return [curr , series ]
213
+
214
+ #... and it must be some data
215
+ else :
216
+ b = remaining .pop (0 )
217
+ if len (remaining ) > 0 :
218
+ if isinstance (remaining [0 ], str ):
219
+ c = remaining .pop (0 )
220
+ return [curr , b , c ]
221
+ else :
222
+ return [curr , b ]
223
+ else :
224
+ if series is None :
225
+ raise ValueError (noinfo_msg )
226
+
227
+
239
228
##### -------------------------------------------------------------------------
240
229
#---- --- Locators ---
241
230
##### -------------------------------------------------------------------------
@@ -816,7 +805,36 @@ def __call__(self, x, pos=0):
816
805
fmt = self .formatdict .pop (x , '' )
817
806
return Period (int (x ), self .freq ).strftime (fmt )
818
807
819
- # Do we need these monkey patch methods for convenience?
808
+ # Patch methods for subplot. Only format_dateaxis is currently used.
809
+ # Do we need the rest for convenience?
810
+
811
+ def format_dateaxis (subplot , freq ):
812
+ """
813
+ Pretty-formats the date axis (x-axis).
814
+
815
+ Major and minor ticks are automatically set for the frequency of the
816
+ current underlying series. As the dynamic mode is activated by
817
+ default, changing the limits of the x axis will intelligently change
818
+ the positions of the ticks.
819
+ """
820
+ majlocator = TimeSeries_DateLocator (freq , dynamic_mode = True ,
821
+ minor_locator = False ,
822
+ plot_obj = subplot )
823
+ minlocator = TimeSeries_DateLocator (freq , dynamic_mode = True ,
824
+ minor_locator = True ,
825
+ plot_obj = subplot )
826
+ subplot .xaxis .set_major_locator (majlocator )
827
+ subplot .xaxis .set_minor_locator (minlocator )
828
+
829
+ majformatter = TimeSeries_DateFormatter (freq , dynamic_mode = True ,
830
+ minor_locator = False ,
831
+ plot_obj = subplot )
832
+ minformatter = TimeSeries_DateFormatter (freq , dynamic_mode = True ,
833
+ minor_locator = True ,
834
+ plot_obj = subplot )
835
+ subplot .xaxis .set_major_formatter (majformatter )
836
+ subplot .xaxis .set_minor_formatter (minformatter )
837
+ pylab .draw_if_interactive ()
820
838
821
839
def add_yaxis (fsp = None , position = 'right' , yscale = None , basey = 10 , subsy = None ):
822
840
"""
0 commit comments