11
11
import pandas .core .indexing as indexing
12
12
from pandas .core .indexing import _maybe_convert_indices
13
13
from pandas .tseries .index import DatetimeIndex
14
+ from pandas .tseries .period import PeriodIndex
14
15
from pandas .core .internals import BlockManager
15
16
import pandas .core .common as com
17
+ import pandas .core .datetools as datetools
16
18
from pandas import compat , _np_version_under1p7
17
19
from pandas .compat import map , zip , lrange
18
20
from pandas .core .common import (isnull , notnull , is_list_like ,
@@ -2667,7 +2669,40 @@ def cummin(self, axis=None, skipna=True):
2667
2669
result = np .minimum .accumulate (y , axis )
2668
2670
return self ._wrap_array (result , self .axes , copy = False )
2669
2671
2670
- def tshift (self , periods = 1 , freq = None , ** kwds ):
2672
+ def shift (self , periods = 1 , freq = None , axis = 0 , ** kwds ):
2673
+ """
2674
+ Shift the index of the DataFrame by desired number of periods with an
2675
+ optional time freq
2676
+
2677
+ Parameters
2678
+ ----------
2679
+ periods : int
2680
+ Number of periods to move, can be positive or negative
2681
+ freq : DateOffset, timedelta, or time rule string, optional
2682
+ Increment to use from datetools module or time rule (e.g. 'EOM')
2683
+
2684
+ Notes
2685
+ -----
2686
+ If freq is specified then the index values are shifted but the data
2687
+ if not realigned
2688
+
2689
+ Returns
2690
+ -------
2691
+ shifted : DataFrame
2692
+ """
2693
+ if periods == 0 :
2694
+ return self
2695
+
2696
+ if freq is None and not len (kwds ):
2697
+ block_axis = self ._get_block_manager_axis (axis )
2698
+ indexer = com ._shift_indexer (len (self ), periods )
2699
+ new_data = self ._data .shift (indexer , periods , axis = block_axis )
2700
+ else :
2701
+ return self .tshift (periods , freq , ** kwds )
2702
+
2703
+ return self ._constructor (new_data )
2704
+
2705
+ def tshift (self , periods = 1 , freq = None , axis = 0 , ** kwds ):
2671
2706
"""
2672
2707
Shift the time index, using the index's frequency if available
2673
2708
@@ -2677,6 +2712,8 @@ def tshift(self, periods=1, freq=None, **kwds):
2677
2712
Number of periods to move, can be positive or negative
2678
2713
freq : DateOffset, timedelta, or time rule string, default None
2679
2714
Increment to use from datetools module or time rule (e.g. 'EOM')
2715
+ axis : int or basestring
2716
+ Corresponds to the axis that contains the Index
2680
2717
2681
2718
Notes
2682
2719
-----
@@ -2686,19 +2723,45 @@ def tshift(self, periods=1, freq=None, **kwds):
2686
2723
2687
2724
Returns
2688
2725
-------
2689
- shifted : Series
2726
+ shifted : NDFrame
2690
2727
"""
2728
+ from pandas .core .datetools import _resolve_offset
2729
+
2730
+ index = self ._get_axis (axis )
2691
2731
if freq is None :
2692
- freq = getattr (self . index , 'freq' , None )
2732
+ freq = getattr (index , 'freq' , None )
2693
2733
2694
2734
if freq is None :
2695
- freq = getattr (self . index , 'inferred_freq' , None )
2735
+ freq = getattr (index , 'inferred_freq' , None )
2696
2736
2697
2737
if freq is None :
2698
2738
msg = 'Freq was not given and was not set in the index'
2699
2739
raise ValueError (msg )
2700
2740
2701
- return self .shift (periods , freq , ** kwds )
2741
+
2742
+ if periods == 0 :
2743
+ return self
2744
+
2745
+ offset = _resolve_offset (freq , kwds )
2746
+
2747
+ if isinstance (offset , compat .string_types ):
2748
+ offset = datetools .to_offset (offset )
2749
+
2750
+ block_axis = self ._get_block_manager_axis (axis )
2751
+ if isinstance (index , PeriodIndex ):
2752
+ orig_offset = datetools .to_offset (index .freq )
2753
+ if offset == orig_offset :
2754
+ new_data = self ._data .copy ()
2755
+ new_data .axes [block_axis ] = index .shift (periods )
2756
+ else :
2757
+ msg = ('Given freq %s does not match PeriodIndex freq %s' %
2758
+ (offset .rule_code , orig_offset .rule_code ))
2759
+ raise ValueError (msg )
2760
+ else :
2761
+ new_data = self ._data .copy ()
2762
+ new_data .axes [block_axis ] = index .shift (periods , offset )
2763
+
2764
+ return self ._constructor (new_data )
2702
2765
2703
2766
def truncate (self , before = None , after = None , copy = True ):
2704
2767
"""Function truncate a sorted DataFrame / Series before and/or after
0 commit comments