@@ -509,6 +509,56 @@ def test_equals_op(self):
509
509
tm .assert_numpy_array_equal (index_a == item , expected3 )
510
510
tm .assert_numpy_array_equal (series_a == item , expected3 )
511
511
512
+ def test_numpy_ufuncs (self ):
513
+ # test ufuncs of numpy 1.9.2. see:
514
+ # http://docs.scipy.org/doc/numpy/reference/ufuncs.html
515
+
516
+ # some functions are skipped because it may return different result
517
+ # for unicode input depending on numpy version
518
+
519
+ for name , idx in compat .iteritems (self .indices ):
520
+ for func in [np .exp , np .exp2 , np .expm1 , np .log , np .log2 , np .log10 ,
521
+ np .log1p , np .sqrt , np .sin , np .cos ,
522
+ np .tan , np .arcsin , np .arccos , np .arctan ,
523
+ np .sinh , np .cosh , np .tanh , np .arcsinh , np .arccosh ,
524
+ np .arctanh , np .deg2rad , np .rad2deg ]:
525
+ if isinstance (idx , pd .tseries .base .DatetimeIndexOpsMixin ):
526
+ # raise TypeError or ValueError (PeriodIndex)
527
+ # PeriodIndex behavior should be changed in future version
528
+ with tm .assertRaises (Exception ):
529
+ func (idx )
530
+ elif isinstance (idx , (Float64Index , Int64Index )):
531
+ # coerces to float (e.g. np.sin)
532
+ result = func (idx )
533
+ exp = Index (func (idx .values ), name = idx .name )
534
+ self .assert_index_equal (result , exp )
535
+ self .assertIsInstance (result , pd .Float64Index )
536
+ else :
537
+ # raise AttributeError or TypeError
538
+ if len (idx ) == 0 :
539
+ continue
540
+ else :
541
+ with tm .assertRaises (Exception ):
542
+ func (idx )
543
+
544
+ for func in [np .isfinite , np .isinf , np .isnan , np .signbit ]:
545
+ if isinstance (idx , pd .tseries .base .DatetimeIndexOpsMixin ):
546
+ # raise TypeError or ValueError (PeriodIndex)
547
+ with tm .assertRaises (Exception ):
548
+ func (idx )
549
+ elif isinstance (idx , (Float64Index , Int64Index )):
550
+ # results in bool array
551
+ result = func (idx )
552
+ exp = func (idx .values )
553
+ self .assertIsInstance (result , np .ndarray )
554
+ tm .assertNotIsInstance (result , Index )
555
+ else :
556
+ if len (idx ) == 0 :
557
+ continue
558
+ else :
559
+ with tm .assertRaises (Exception ):
560
+ func (idx )
561
+
512
562
513
563
class TestIndex (Base , tm .TestCase ):
514
564
_holder = Index
@@ -2848,6 +2898,41 @@ def test_slice_keep_name(self):
2848
2898
idx = Int64Index ([1 , 2 ], name = 'asdf' )
2849
2899
self .assertEqual (idx .name , idx [1 :].name )
2850
2900
2901
+ def test_ufunc_coercions (self ):
2902
+ idx = pd .Int64Index ([1 , 2 , 3 , 4 , 5 ], name = 'x' )
2903
+
2904
+ result = np .sqrt (idx )
2905
+ tm .assertIsInstance (result , Float64Index )
2906
+ exp = pd .Float64Index (np .sqrt (np .array ([1 , 2 , 3 , 4 , 5 ])), name = 'x' )
2907
+ tm .assert_index_equal (result , exp )
2908
+
2909
+ result = np .divide (idx , 2. )
2910
+ tm .assertIsInstance (result , Float64Index )
2911
+ exp = pd .Float64Index ([0.5 , 1. , 1.5 , 2. , 2.5 ], name = 'x' )
2912
+ tm .assert_index_equal (result , exp )
2913
+
2914
+ # _evaluate_numeric_binop
2915
+ result = idx + 2.
2916
+ tm .assertIsInstance (result , Float64Index )
2917
+ exp = pd .Float64Index ([3. , 4. , 5. , 6. , 7. ], name = 'x' )
2918
+ tm .assert_index_equal (result , exp )
2919
+
2920
+ result = idx - 2.
2921
+ tm .assertIsInstance (result , Float64Index )
2922
+ exp = pd .Float64Index ([- 1. , 0. , 1. , 2. , 3. ], name = 'x' )
2923
+ tm .assert_index_equal (result , exp )
2924
+
2925
+ result = idx * 1.
2926
+ tm .assertIsInstance (result , Float64Index )
2927
+ exp = pd .Float64Index ([1. , 2. , 3. , 4. , 5. ], name = 'x' )
2928
+ tm .assert_index_equal (result , exp )
2929
+
2930
+ result = idx / 2.
2931
+ tm .assertIsInstance (result , Float64Index )
2932
+ exp = pd .Float64Index ([0.5 , 1. , 1.5 , 2. , 2.5 ], name = 'x' )
2933
+ tm .assert_index_equal (result , exp )
2934
+
2935
+
2851
2936
class DatetimeLike (Base ):
2852
2937
2853
2938
def test_str (self ):
@@ -3101,7 +3186,9 @@ def test_get_loc(self):
3101
3186
tolerance = timedelta (1 )), 1 )
3102
3187
with tm .assertRaisesRegexp (ValueError , 'must be convertible' ):
3103
3188
idx .get_loc ('2000-01-10' , method = 'nearest' , tolerance = 'foo' )
3104
- with tm .assertRaisesRegexp (ValueError , 'different freq' ):
3189
+
3190
+ msg = 'Input has different freq from PeriodIndex\\ (freq=D\\ )'
3191
+ with tm .assertRaisesRegexp (ValueError , msg ):
3105
3192
idx .get_loc ('2000-01-10' , method = 'nearest' , tolerance = '1 hour' )
3106
3193
with tm .assertRaises (KeyError ):
3107
3194
idx .get_loc ('2000-01-10' , method = 'nearest' , tolerance = '1 day' )
@@ -3119,7 +3206,8 @@ def test_get_indexer(self):
3119
3206
idx .get_indexer (target , 'nearest' , tolerance = '1 hour' ),
3120
3207
[0 , - 1 , 1 ])
3121
3208
3122
- with self .assertRaisesRegexp (ValueError , 'different freq' ):
3209
+ msg = 'Input has different freq from PeriodIndex\\ (freq=H\\ )'
3210
+ with self .assertRaisesRegexp (ValueError , msg ):
3123
3211
idx .get_indexer (target , 'nearest' , tolerance = '1 minute' )
3124
3212
3125
3213
tm .assert_numpy_array_equal (
@@ -3215,6 +3303,44 @@ def test_numeric_compat(self):
3215
3303
def test_pickle_compat_construction (self ):
3216
3304
pass
3217
3305
3306
+ def test_ufunc_coercions (self ):
3307
+ # normal ops are also tested in tseries/test_timedeltas.py
3308
+ idx = TimedeltaIndex (['2H' , '4H' , '6H' , '8H' , '10H' ],
3309
+ freq = '2H' , name = 'x' )
3310
+
3311
+ for result in [idx * 2 , np .multiply (idx , 2 )]:
3312
+ tm .assertIsInstance (result , TimedeltaIndex )
3313
+ exp = TimedeltaIndex (['4H' , '8H' , '12H' , '16H' , '20H' ],
3314
+ freq = '4H' , name = 'x' )
3315
+ tm .assert_index_equal (result , exp )
3316
+ self .assertEqual (result .freq , '4H' )
3317
+
3318
+ for result in [idx / 2 , np .divide (idx , 2 )]:
3319
+ tm .assertIsInstance (result , TimedeltaIndex )
3320
+ exp = TimedeltaIndex (['1H' , '2H' , '3H' , '4H' , '5H' ],
3321
+ freq = 'H' , name = 'x' )
3322
+ tm .assert_index_equal (result , exp )
3323
+ self .assertEqual (result .freq , 'H' )
3324
+
3325
+ idx = TimedeltaIndex (['2H' , '4H' , '6H' , '8H' , '10H' ],
3326
+ freq = '2H' , name = 'x' )
3327
+ for result in [ - idx , np .negative (idx )]:
3328
+ tm .assertIsInstance (result , TimedeltaIndex )
3329
+ exp = TimedeltaIndex (['-2H' , '-4H' , '-6H' , '-8H' , '-10H' ],
3330
+ freq = '-2H' , name = 'x' )
3331
+ tm .assert_index_equal (result , exp )
3332
+ self .assertEqual (result .freq , None )
3333
+
3334
+ idx = TimedeltaIndex (['-2H' , '-1H' , '0H' , '1H' , '2H' ],
3335
+ freq = 'H' , name = 'x' )
3336
+ for result in [ abs (idx ), np .absolute (idx )]:
3337
+ tm .assertIsInstance (result , TimedeltaIndex )
3338
+ exp = TimedeltaIndex (['2H' , '1H' , '0H' , '1H' , '2H' ],
3339
+ freq = None , name = 'x' )
3340
+ tm .assert_index_equal (result , exp )
3341
+ self .assertEqual (result .freq , None )
3342
+
3343
+
3218
3344
class TestMultiIndex (Base , tm .TestCase ):
3219
3345
_holder = MultiIndex
3220
3346
_multiprocess_can_split_ = True
0 commit comments