@@ -755,9 +755,9 @@ class MPLPlot(object):
755
755
_default_rot = 0
756
756
757
757
_pop_attributes = ['label' , 'style' , 'logy' , 'logx' , 'loglog' ,
758
- 'mark_right' ]
758
+ 'mark_right' , 'stacked' ]
759
759
_attr_defaults = {'logy' : False , 'logx' : False , 'loglog' : False ,
760
- 'mark_right' : True }
760
+ 'mark_right' : True , 'stacked' : False }
761
761
762
762
def __init__ (self , data , kind = None , by = None , subplots = False , sharex = True ,
763
763
sharey = False , use_index = True ,
@@ -1080,7 +1080,6 @@ def _make_legend(self):
1080
1080
for ax in self .axes :
1081
1081
ax .legend (loc = 'best' )
1082
1082
1083
-
1084
1083
def _get_ax_legend (self , ax ):
1085
1084
leg = ax .get_legend ()
1086
1085
other_ax = (getattr (ax , 'right_ax' , None ) or
@@ -1139,12 +1138,22 @@ def _get_plot_function(self):
1139
1138
Returns the matplotlib plotting function (plot or errorbar) based on
1140
1139
the presence of errorbar keywords.
1141
1140
'''
1142
-
1143
- if all (e is None for e in self .errors .values ()):
1144
- plotf = self .plt .Axes .plot
1145
- else :
1146
- plotf = self .plt .Axes .errorbar
1147
-
1141
+ errorbar = any (e is not None for e in self .errors .values ())
1142
+ def plotf (ax , x , y , style = None , ** kwds ):
1143
+ mask = com .isnull (y )
1144
+ if mask .any ():
1145
+ y = np .ma .array (y )
1146
+ y = np .ma .masked_where (mask , y )
1147
+
1148
+ if errorbar :
1149
+ return self .plt .Axes .errorbar (ax , x , y , ** kwds )
1150
+ else :
1151
+ # prevent style kwarg from going to errorbar, where it is unsupported
1152
+ if style is not None :
1153
+ args = (ax , x , y , style )
1154
+ else :
1155
+ args = (ax , x , y )
1156
+ return self .plt .Axes .plot (* args , ** kwds )
1148
1157
return plotf
1149
1158
1150
1159
def _get_index_name (self ):
@@ -1472,11 +1481,9 @@ def _post_plot_logic(self):
1472
1481
class LinePlot (MPLPlot ):
1473
1482
1474
1483
def __init__ (self , data , ** kwargs ):
1475
- self .stacked = kwargs .pop ('stacked' , False )
1476
- if self .stacked :
1477
- data = data .fillna (value = 0 )
1478
-
1479
1484
MPLPlot .__init__ (self , data , ** kwargs )
1485
+ if self .stacked :
1486
+ self .data = self .data .fillna (value = 0 )
1480
1487
self .x_compat = plot_params ['x_compat' ]
1481
1488
if 'x_compat' in self .kwds :
1482
1489
self .x_compat = bool (self .kwds .pop ('x_compat' ))
@@ -1533,56 +1540,39 @@ def _is_ts_plot(self):
1533
1540
return not self .x_compat and self .use_index and self ._use_dynamic_x ()
1534
1541
1535
1542
def _make_plot (self ):
1536
- self ._pos_prior = np .zeros (len (self .data ))
1537
- self ._neg_prior = np .zeros (len (self .data ))
1543
+ self ._initialize_prior (len (self .data ))
1538
1544
1539
1545
if self ._is_ts_plot ():
1540
1546
data = self ._maybe_convert_index (self .data )
1541
- self ._make_ts_plot (data )
1547
+ x = data .index # dummy, not used
1548
+ plotf = self ._get_ts_plot_function ()
1549
+ it = self ._iter_data (data = data , keep_index = True )
1542
1550
else :
1543
1551
x = self ._get_xticks (convert_period = True )
1544
-
1545
1552
plotf = self ._get_plot_function ()
1546
- colors = self ._get_colors ()
1547
-
1548
- for i , (label , y ) in enumerate (self ._iter_data ()):
1549
- ax = self ._get_ax (i )
1550
- style = self ._get_style (i , label )
1551
- kwds = self .kwds .copy ()
1552
- self ._maybe_add_color (colors , kwds , style , i )
1553
+ it = self ._iter_data ()
1553
1554
1554
- errors = self ._get_errorbars (label = label , index = i )
1555
- kwds = dict (kwds , ** errors )
1556
-
1557
- label = com .pprint_thing (label ) # .encode('utf-8')
1558
- kwds ['label' ] = label
1559
-
1560
- y_values = self ._get_stacked_values (y , label )
1561
-
1562
- if not self .stacked :
1563
- mask = com .isnull (y_values )
1564
- if mask .any ():
1565
- y_values = np .ma .array (y_values )
1566
- y_values = np .ma .masked_where (mask , y_values )
1555
+ colors = self ._get_colors ()
1556
+ for i , (label , y ) in enumerate (it ):
1557
+ ax = self ._get_ax (i )
1558
+ style = self ._get_style (i , label )
1559
+ kwds = self .kwds .copy ()
1560
+ self ._maybe_add_color (colors , kwds , style , i )
1567
1561
1568
- # prevent style kwarg from going to errorbar, where it is unsupported
1569
- if style is not None and plotf .__name__ != 'errorbar' :
1570
- args = (ax , x , y_values , style )
1571
- else :
1572
- args = (ax , x , y_values )
1562
+ errors = self ._get_errorbars (label = label , index = i )
1563
+ kwds = dict (kwds , ** errors )
1573
1564
1574
- newlines = plotf (* args , ** kwds )
1575
- self ._add_legend_handle (newlines [0 ], label , index = i )
1565
+ label = com .pprint_thing (label ) # .encode('utf-8')
1566
+ kwds ['label' ] = label
1567
+ y_values = self ._get_stacked_values (y , label )
1576
1568
1577
- if self .stacked and not self .subplots :
1578
- if (y >= 0 ).all ():
1579
- self ._pos_prior += y
1580
- elif (y <= 0 ).all ():
1581
- self ._neg_prior += y
1569
+ newlines = plotf (ax , x , y_values , style = style , ** kwds )
1570
+ self ._update_prior (y )
1571
+ self ._add_legend_handle (newlines [0 ], label , index = i )
1582
1572
1583
- lines = _get_all_lines (ax )
1584
- left , right = _get_xlim (lines )
1585
- ax .set_xlim (left , right )
1573
+ lines = _get_all_lines (ax )
1574
+ left , right = _get_xlim (lines )
1575
+ ax .set_xlim (left , right )
1586
1576
1587
1577
def _get_stacked_values (self , y , label ):
1588
1578
if self .stacked :
@@ -1599,46 +1589,26 @@ def _get_stacked_values(self, y, label):
1599
1589
def _get_ts_plot_function (self ):
1600
1590
from pandas .tseries .plotting import tsplot
1601
1591
plotf = self ._get_plot_function ()
1602
-
1603
- def _plot (data , ax , label , style , ** kwds ):
1604
- # errorbar function does not support style argument
1605
- if plotf .__name__ == 'errorbar' :
1606
- lines = tsplot (data , plotf , ax = ax , label = label ,
1607
- ** kwds )
1608
- return lines
1609
- else :
1610
- lines = tsplot (data , plotf , ax = ax , label = label ,
1611
- style = style , ** kwds )
1612
- return lines
1592
+ def _plot (ax , x , data , style = None , ** kwds ):
1593
+ # accept x to be consistent with normal plot func,
1594
+ # x is not passed to tsplot as it uses data.index as x coordinate
1595
+ lines = tsplot (data , plotf , ax = ax , style = style , ** kwds )
1596
+ return lines
1613
1597
return _plot
1614
1598
1615
- def _make_ts_plot (self , data , ** kwargs ):
1616
- colors = self ._get_colors ()
1617
- plotf = self ._get_ts_plot_function ()
1618
-
1619
- it = self ._iter_data (data = data , keep_index = True )
1620
- for i , (label , y ) in enumerate (it ):
1621
- ax = self ._get_ax (i )
1622
- style = self ._get_style (i , label )
1623
- kwds = self .kwds .copy ()
1624
-
1625
- self ._maybe_add_color (colors , kwds , style , i )
1626
-
1627
- errors = self ._get_errorbars (label = label , index = i , xerr = False )
1628
- kwds = dict (kwds , ** errors )
1629
-
1630
- label = com .pprint_thing (label )
1631
-
1632
- y_values = self ._get_stacked_values (y , label )
1633
-
1634
- newlines = plotf (y_values , ax , label , style , ** kwds )
1635
- self ._add_legend_handle (newlines [0 ], label , index = i )
1599
+ def _initialize_prior (self , n ):
1600
+ self ._pos_prior = np .zeros (n )
1601
+ self ._neg_prior = np .zeros (n )
1636
1602
1637
- if self .stacked and not self .subplots :
1638
- if (y >= 0 ).all ():
1639
- self ._pos_prior += y
1640
- elif (y <= 0 ).all ():
1641
- self ._neg_prior += y
1603
+ def _update_prior (self , y ):
1604
+ if self .stacked and not self .subplots :
1605
+ # tsplot resample may changedata length
1606
+ if len (self ._pos_prior ) != len (y ):
1607
+ self ._initialize_prior (len (y ))
1608
+ if (y >= 0 ).all ():
1609
+ self ._pos_prior += y
1610
+ elif (y <= 0 ).all ():
1611
+ self ._neg_prior += y
1642
1612
1643
1613
def _maybe_convert_index (self , data ):
1644
1614
# tsplot converts automatically, but don't want to convert index
@@ -1707,30 +1677,25 @@ def _get_plot_function(self):
1707
1677
if self .logy or self .loglog :
1708
1678
raise ValueError ("Log-y scales are not supported in area plot" )
1709
1679
else :
1710
- f = LinePlot ._get_plot_function (self )
1711
-
1712
- def plotf (* args , ** kwds ):
1713
- lines = f (* args , ** kwds )
1680
+ f = MPLPlot ._get_plot_function (self )
1681
+ def plotf (ax , x , y , style = None , ** kwds ):
1682
+ lines = f (ax , x , y , style = style , ** kwds )
1714
1683
1684
+ # get data from the line
1715
1685
# insert fill_between starting point
1716
- y = args [2 ]
1686
+ xdata , y_values = lines [0 ].get_data (orig = False )
1687
+
1717
1688
if (y >= 0 ).all ():
1718
1689
start = self ._pos_prior
1719
1690
elif (y <= 0 ).all ():
1720
1691
start = self ._neg_prior
1721
1692
else :
1722
1693
start = np .zeros (len (y ))
1723
1694
1724
- # get x data from the line
1725
- # to retrieve x coodinates of tsplot
1726
- xdata = lines [0 ].get_data ()[0 ]
1727
- # remove style
1728
- args = (args [0 ], xdata , start , y )
1729
-
1730
1695
if not 'color' in kwds :
1731
1696
kwds ['color' ] = lines [0 ].get_color ()
1732
1697
1733
- self .plt .Axes .fill_between (* args , ** kwds )
1698
+ self .plt .Axes .fill_between (ax , xdata , start , y_values , ** kwds )
1734
1699
return lines
1735
1700
1736
1701
return plotf
@@ -1746,15 +1711,6 @@ def _add_legend_handle(self, handle, label, index=None):
1746
1711
def _post_plot_logic (self ):
1747
1712
LinePlot ._post_plot_logic (self )
1748
1713
1749
- if self ._is_ts_plot ():
1750
- pass
1751
- else :
1752
- if self .xlim is None :
1753
- for ax in self .axes :
1754
- lines = _get_all_lines (ax )
1755
- left , right = _get_xlim (lines )
1756
- ax .set_xlim (left , right )
1757
-
1758
1714
if self .ylim is None :
1759
1715
if (self .data >= 0 ).all ().all ():
1760
1716
for ax in self .axes :
@@ -1769,12 +1725,8 @@ class BarPlot(MPLPlot):
1769
1725
_default_rot = {'bar' : 90 , 'barh' : 0 }
1770
1726
1771
1727
def __init__ (self , data , ** kwargs ):
1772
- self .stacked = kwargs .pop ('stacked' , False )
1773
-
1774
1728
self .bar_width = kwargs .pop ('width' , 0.5 )
1775
-
1776
1729
pos = kwargs .pop ('position' , 0.5 )
1777
-
1778
1730
kwargs .setdefault ('align' , 'center' )
1779
1731
self .tick_pos = np .arange (len (data ))
1780
1732
0 commit comments