7
7
8
8
import numpy as np
9
9
10
- from pandas ._libs import NaT , lib , tslib , tslibs
10
+ from pandas ._libs import NaT , Timestamp , lib , tslib , tslibs
11
11
import pandas ._libs .internals as libinternals
12
12
from pandas ._libs .tslibs import Timedelta , conversion
13
13
from pandas ._libs .tslibs .timezones import tz_compare
@@ -715,20 +715,6 @@ def _try_cast_result(self, result, dtype=None):
715
715
# may need to change the dtype here
716
716
return maybe_downcast_to_dtype (result , dtype )
717
717
718
- def _coerce_values (self , values ):
719
- """
720
- Coerce values (usually derived from self.values) for an operation.
721
-
722
- Parameters
723
- ----------
724
- values : ndarray or ExtensionArray
725
-
726
- Returns
727
- -------
728
- ndarray or ExtensionArray
729
- """
730
- return values
731
-
732
718
def _try_coerce_args (self , other ):
733
719
""" provide coercion to our input arguments """
734
720
@@ -817,7 +803,7 @@ def replace(
817
803
convert = convert ,
818
804
)
819
805
820
- values = self ._coerce_values ( self . values )
806
+ values = self .values
821
807
to_replace = self ._try_coerce_args (to_replace )
822
808
823
809
mask = missing .mask_missing (values , to_replace )
@@ -882,7 +868,6 @@ def setitem(self, indexer, value):
882
868
if self ._can_hold_element (value ):
883
869
value = self ._try_coerce_args (value )
884
870
885
- values = self ._coerce_values (values )
886
871
# can keep its own dtype
887
872
if hasattr (value , "dtype" ) and is_dtype_equal (values .dtype , value .dtype ):
888
873
dtype = self .dtype
@@ -1229,7 +1214,6 @@ def _interpolate_with_fill(
1229
1214
return [self .copy ()]
1230
1215
1231
1216
values = self .values if inplace else self .values .copy ()
1232
- values = self ._coerce_values (values )
1233
1217
fill_value = self ._try_coerce_args (fill_value )
1234
1218
values = missing .interpolate_2d (
1235
1219
values ,
@@ -1444,7 +1428,6 @@ def func(cond, values, other):
1444
1428
else :
1445
1429
# see if we can operate on the entire block, or need item-by-item
1446
1430
# or if we are a single block (ndim == 1)
1447
- values = self ._coerce_values (values )
1448
1431
try :
1449
1432
result = func (cond , values , other )
1450
1433
except TypeError :
@@ -1548,14 +1531,13 @@ def quantile(self, qs, interpolation="linear", axis=0):
1548
1531
# We need to operate on i8 values for datetimetz
1549
1532
# but `Block.get_values()` returns an ndarray of objects
1550
1533
# right now. We need an API for "values to do numeric-like ops on"
1551
- values = self .values .asi8
1534
+ values = self .values .view ( "M8[ns]" )
1552
1535
1553
1536
# TODO: NonConsolidatableMixin shape
1554
1537
# Usual shape inconsistencies for ExtensionBlocks
1555
1538
values = values [None , :]
1556
1539
else :
1557
1540
values = self .get_values ()
1558
- values = self ._coerce_values (values )
1559
1541
1560
1542
is_empty = values .shape [axis ] == 0
1561
1543
orig_scalar = not is_list_like (qs )
@@ -1720,7 +1702,6 @@ def putmask(self, mask, new, align=True, inplace=False, axis=0, transpose=False)
1720
1702
# use block's copy logic.
1721
1703
# .values may be an Index which does shallow copy by default
1722
1704
new_values = self .values if inplace else self .copy ().values
1723
- new_values = self ._coerce_values (new_values )
1724
1705
new = self ._try_coerce_args (new )
1725
1706
1726
1707
if isinstance (new , np .ndarray ) and len (new ) == len (mask ):
@@ -1919,12 +1900,6 @@ def _try_cast_result(self, result, dtype=None):
1919
1900
result could also be an EA Array itself, in which case it
1920
1901
is already a 1-D array
1921
1902
"""
1922
- try :
1923
-
1924
- result = self ._holder ._from_sequence (result .ravel (), dtype = dtype )
1925
- except Exception :
1926
- pass
1927
-
1928
1903
return result
1929
1904
1930
1905
def formatting_values (self ):
@@ -2304,8 +2279,8 @@ def _try_coerce_args(self, other):
2304
2279
if is_valid_nat_for_dtype (other , self .dtype ):
2305
2280
other = np .datetime64 ("NaT" , "ns" )
2306
2281
elif isinstance (other , (datetime , np .datetime64 , date )):
2307
- other = self . _box_func (other )
2308
- if getattr ( other , "tz" ) is not None :
2282
+ other = Timestamp (other )
2283
+ if other . tz is not None :
2309
2284
raise TypeError ("cannot coerce a Timestamp with a tz on a naive Block" )
2310
2285
other = other .asm8
2311
2286
elif hasattr (other , "dtype" ) and is_datetime64_dtype (other ):
@@ -2320,18 +2295,11 @@ def _try_coerce_args(self, other):
2320
2295
2321
2296
def _try_coerce_result (self , result ):
2322
2297
""" reverse of try_coerce_args """
2323
- if isinstance (result , np .ndarray ):
2324
- if result .dtype .kind in ["i" , "f" ]:
2325
- result = result .astype ("M8[ns]" )
2326
-
2327
- elif isinstance (result , (np .integer , np .float , np .datetime64 )):
2328
- result = self ._box_func (result )
2298
+ if isinstance (result , np .ndarray ) and result .dtype .kind == "i" :
2299
+ # needed for _interpolate_with_ffill
2300
+ result = result .view ("M8[ns]" )
2329
2301
return result
2330
2302
2331
- @property
2332
- def _box_func (self ):
2333
- return tslibs .Timestamp
2334
-
2335
2303
def to_native_types (
2336
2304
self , slicer = None , na_rep = None , date_format = None , quoting = None , ** kwargs
2337
2305
):
@@ -2387,6 +2355,7 @@ class DatetimeTZBlock(ExtensionBlock, DatetimeBlock):
2387
2355
is_extension = True
2388
2356
2389
2357
_can_hold_element = DatetimeBlock ._can_hold_element
2358
+ fill_value = np .datetime64 ("NaT" , "ns" )
2390
2359
2391
2360
@property
2392
2361
def _holder (self ):
@@ -2442,7 +2411,7 @@ def get_values(self, dtype=None):
2442
2411
"""
2443
2412
values = self .values
2444
2413
if is_object_dtype (dtype ):
2445
- values = values ._box_values ( values . _data )
2414
+ values = values .astype ( object )
2446
2415
2447
2416
values = np .asarray (values )
2448
2417
@@ -2468,9 +2437,6 @@ def _slice(self, slicer):
2468
2437
return self .values [loc ]
2469
2438
return self .values [slicer ]
2470
2439
2471
- def _coerce_values (self , values ):
2472
- return _block_shape (values , ndim = self .ndim )
2473
-
2474
2440
def _try_coerce_args (self , other ):
2475
2441
"""
2476
2442
localize and return i8 for the values
@@ -2483,17 +2449,7 @@ def _try_coerce_args(self, other):
2483
2449
-------
2484
2450
base-type other
2485
2451
"""
2486
-
2487
- if isinstance (other , ABCSeries ):
2488
- other = self ._holder (other )
2489
-
2490
- if isinstance (other , bool ):
2491
- raise TypeError
2492
- elif is_datetime64_dtype (other ):
2493
- # add the tz back
2494
- other = self ._holder (other , dtype = self .dtype )
2495
-
2496
- elif is_valid_nat_for_dtype (other , self .dtype ):
2452
+ if is_valid_nat_for_dtype (other , self .dtype ):
2497
2453
other = np .datetime64 ("NaT" , "ns" )
2498
2454
elif isinstance (other , self ._holder ):
2499
2455
if not tz_compare (other .tz , self .values .tz ):
@@ -2513,22 +2469,23 @@ def _try_coerce_args(self, other):
2513
2469
def _try_coerce_result (self , result ):
2514
2470
""" reverse of try_coerce_args """
2515
2471
if isinstance (result , np .ndarray ):
2516
- if result .dtype .kind in ["i" , "f" ]:
2517
- result = result .astype ("M8[ns]" )
2472
+ if result .ndim == 2 :
2473
+ # kludge for 2D blocks with 1D EAs
2474
+ result = result [0 , :]
2475
+ if result .dtype == np .float64 :
2476
+ # needed for post-groupby.median
2477
+ result = self ._holder ._from_sequence (
2478
+ result .astype (np .int64 ), freq = None , dtype = self .values .dtype
2479
+ )
2480
+ elif result .dtype == "M8[ns]" :
2481
+ # otherwise we get here via quantile and already have M8[ns]
2482
+ result = self ._holder ._simple_new (
2483
+ result , freq = None , dtype = self .values .dtype
2484
+ )
2518
2485
2519
- elif isinstance (result , (np .integer , np .float , np .datetime64 )):
2486
+ elif isinstance (result , np .datetime64 ):
2487
+ # also for post-quantile
2520
2488
result = self ._box_func (result )
2521
-
2522
- if isinstance (result , np .ndarray ):
2523
- # allow passing of > 1dim if its trivial
2524
-
2525
- if result .ndim > 1 :
2526
- result = result .reshape (np .prod (result .shape ))
2527
- # GH#24096 new values invalidates a frequency
2528
- result = self ._holder ._simple_new (
2529
- result , freq = None , dtype = self .values .dtype
2530
- )
2531
-
2532
2489
return result
2533
2490
2534
2491
@property
@@ -2627,10 +2584,6 @@ def __init__(self, values, placement, ndim=None):
2627
2584
def _holder (self ):
2628
2585
return TimedeltaArray
2629
2586
2630
- @property
2631
- def _box_func (self ):
2632
- return lambda x : Timedelta (x , unit = "ns" )
2633
-
2634
2587
def _can_hold_element (self , element ):
2635
2588
tipo = maybe_infer_dtype_type (element )
2636
2589
if tipo is not None :
@@ -2688,15 +2641,6 @@ def _try_coerce_args(self, other):
2688
2641
2689
2642
def _try_coerce_result (self , result ):
2690
2643
""" reverse of try_coerce_args / try_operate """
2691
- if isinstance (result , np .ndarray ):
2692
- mask = isna (result )
2693
- if result .dtype .kind in ["i" , "f" ]:
2694
- result = result .astype ("m8[ns]" )
2695
- result [mask ] = np .timedelta64 ("NaT" , "ns" )
2696
-
2697
- elif isinstance (result , (np .integer , np .float )):
2698
- result = self ._box_func (result )
2699
-
2700
2644
return result
2701
2645
2702
2646
def should_store (self , value ):
0 commit comments