@@ -653,6 +653,20 @@ def _can_hold_element(self, element: Any) -> bool:
653
653
return issubclass (tipo .type , dtype )
654
654
return isinstance (element , dtype )
655
655
656
+ def should_store (self , value : ArrayLike ) -> bool :
657
+ """
658
+ Should we set self.values[indexer] = value inplace or do we need to cast?
659
+
660
+ Parameters
661
+ ----------
662
+ value : np.ndarray or ExtensionArray
663
+
664
+ Returns
665
+ -------
666
+ bool
667
+ """
668
+ return is_dtype_equal (value .dtype , self .dtype )
669
+
656
670
def to_native_types (self , slicer = None , na_rep = "nan" , quoting = None , ** kwargs ):
657
671
""" convert to our native types format, slicing if desired """
658
672
values = self .values
@@ -1752,10 +1766,7 @@ def setitem(self, indexer, value):
1752
1766
1753
1767
def get_values (self , dtype = None ):
1754
1768
# ExtensionArrays must be iterable, so this works.
1755
- values = np .asarray (self .values )
1756
- if values .ndim == self .ndim - 1 :
1757
- values = values .reshape ((1 ,) + values .shape )
1758
- return values
1769
+ return np .asarray (self .values ).reshape (self .shape )
1759
1770
1760
1771
def array_values (self ) -> ExtensionArray :
1761
1772
return self .values
@@ -2021,11 +2032,6 @@ def to_native_types(
2021
2032
)
2022
2033
return formatter .get_result_as_array ()
2023
2034
2024
- def should_store (self , value : ArrayLike ) -> bool :
2025
- # when inserting a column should not coerce integers to floats
2026
- # unnecessarily
2027
- return issubclass (value .dtype .type , np .floating ) and value .dtype == self .dtype
2028
-
2029
2035
2030
2036
class ComplexBlock (FloatOrComplexBlock ):
2031
2037
__slots__ = ()
@@ -2058,9 +2064,6 @@ def _can_hold_element(self, element: Any) -> bool:
2058
2064
)
2059
2065
return is_integer (element )
2060
2066
2061
- def should_store (self , value : ArrayLike ) -> bool :
2062
- return is_integer_dtype (value ) and value .dtype == self .dtype
2063
-
2064
2067
2065
2068
class DatetimeLikeBlockMixin :
2066
2069
"""Mixin class for DatetimeBlock, DatetimeTZBlock, and TimedeltaBlock."""
@@ -2069,9 +2072,6 @@ class DatetimeLikeBlockMixin:
2069
2072
def _holder (self ):
2070
2073
return DatetimeArray
2071
2074
2072
- def should_store (self , value ):
2073
- return is_dtype_equal (self .dtype , value .dtype )
2074
-
2075
2075
@property
2076
2076
def fill_value (self ):
2077
2077
return np .datetime64 ("NaT" , "ns" )
@@ -2081,15 +2081,16 @@ def get_values(self, dtype=None):
2081
2081
return object dtype as boxed values, such as Timestamps/Timedelta
2082
2082
"""
2083
2083
if is_object_dtype (dtype ):
2084
- values = self .values .ravel ()
2085
- result = self ._holder (values ).astype (object )
2086
- return result .reshape (self .values .shape )
2084
+ return self ._holder (self .values ).astype (object )
2087
2085
return self .values
2088
2086
2089
2087
def internal_values (self ):
2090
2088
# Override to return DatetimeArray and TimedeltaArray
2091
2089
return self .array_values ()
2092
2090
2091
+ def array_values (self ):
2092
+ return self ._holder (self .values )
2093
+
2093
2094
def iget (self , key ):
2094
2095
# GH#31649 we need to wrap scalars in Timestamp/Timedelta
2095
2096
# TODO(EA2D): this can be removed if we ever have 2D EA
@@ -2216,12 +2217,6 @@ def set(self, locs, values):
2216
2217
2217
2218
self .values [locs ] = values
2218
2219
2219
- def external_values (self ):
2220
- return np .asarray (self .values .astype ("datetime64[ns]" , copy = False ))
2221
-
2222
- def array_values (self ) -> ExtensionArray :
2223
- return DatetimeArray ._simple_new (self .values )
2224
-
2225
2220
2226
2221
class DatetimeTZBlock (ExtensionBlock , DatetimeBlock ):
2227
2222
""" implement a datetime64 block with a tz attribute """
@@ -2234,7 +2229,7 @@ class DatetimeTZBlock(ExtensionBlock, DatetimeBlock):
2234
2229
_can_hold_element = DatetimeBlock ._can_hold_element
2235
2230
to_native_types = DatetimeBlock .to_native_types
2236
2231
fill_value = np .datetime64 ("NaT" , "ns" )
2237
- should_store = DatetimeBlock .should_store
2232
+ should_store = Block .should_store
2238
2233
2239
2234
@property
2240
2235
def _holder (self ):
@@ -2293,14 +2288,13 @@ def get_values(self, dtype=None):
2293
2288
if is_object_dtype (dtype ):
2294
2289
values = values .astype (object )
2295
2290
2296
- values = np .asarray (values )
2291
+ # TODO(EA2D): reshape uuncessary with 2D EAs
2292
+ return np .asarray (values ).reshape (self .shape )
2297
2293
2298
- if self .ndim == 2 :
2299
- # Ensure that our shape is correct for DataFrame.
2300
- # ExtensionArrays are always 1-D, even in a DataFrame when
2301
- # the analogous NumPy-backed column would be a 2-D ndarray.
2302
- values = values .reshape (1 , - 1 )
2303
- return values
2294
+ def external_values (self ):
2295
+ # NB: this is different from np.asarray(self.values), since that
2296
+ # return an object-dtype ndarray of Timestamps.
2297
+ return np .asarray (self .values .astype ("datetime64[ns]" , copy = False ))
2304
2298
2305
2299
def _slice (self , slicer ):
2306
2300
""" return a slice of my values """
@@ -2467,12 +2461,6 @@ def to_native_types(self, slicer=None, na_rep=None, quoting=None, **kwargs):
2467
2461
)
2468
2462
return rvalues
2469
2463
2470
- def external_values (self ):
2471
- return np .asarray (self .values .astype ("timedelta64[ns]" , copy = False ))
2472
-
2473
- def array_values (self ) -> ExtensionArray :
2474
- return TimedeltaArray ._simple_new (self .values )
2475
-
2476
2464
2477
2465
class BoolBlock (NumericBlock ):
2478
2466
__slots__ = ()
@@ -2485,11 +2473,6 @@ def _can_hold_element(self, element: Any) -> bool:
2485
2473
return issubclass (tipo .type , np .bool_ )
2486
2474
return isinstance (element , (bool , np .bool_ ))
2487
2475
2488
- def should_store (self , value : ArrayLike ) -> bool :
2489
- return issubclass (value .dtype .type , np .bool_ ) and not is_extension_array_dtype (
2490
- value
2491
- )
2492
-
2493
2476
def replace (
2494
2477
self , to_replace , value , inplace = False , filter = None , regex = False , convert = True
2495
2478
):
@@ -2577,15 +2560,6 @@ def _maybe_downcast(self, blocks: List["Block"], downcast=None) -> List["Block"]
2577
2560
def _can_hold_element (self , element : Any ) -> bool :
2578
2561
return True
2579
2562
2580
- def should_store (self , value : ArrayLike ) -> bool :
2581
- return not (
2582
- issubclass (
2583
- value .dtype .type ,
2584
- (np .integer , np .floating , np .complexfloating , np .datetime64 , np .bool_ ),
2585
- )
2586
- or is_extension_array_dtype (value )
2587
- )
2588
-
2589
2563
def replace (
2590
2564
self , to_replace , value , inplace = False , filter = None , regex = False , convert = True
2591
2565
):
@@ -2816,6 +2790,8 @@ class CategoricalBlock(ExtensionBlock):
2816
2790
_can_hold_na = True
2817
2791
_concatenator = staticmethod (concat_categorical )
2818
2792
2793
+ should_store = Block .should_store
2794
+
2819
2795
def __init__ (self , values , placement , ndim = None ):
2820
2796
# coerce to categorical if we can
2821
2797
values = extract_array (values )
@@ -2826,9 +2802,6 @@ def __init__(self, values, placement, ndim=None):
2826
2802
def _holder (self ):
2827
2803
return Categorical
2828
2804
2829
- def should_store (self , arr : ArrayLike ):
2830
- return isinstance (arr , self ._holder ) and is_dtype_equal (self .dtype , arr .dtype )
2831
-
2832
2805
def to_native_types (self , slicer = None , na_rep = "" , quoting = None , ** kwargs ):
2833
2806
""" convert to our native types format, slicing if desired """
2834
2807
values = self .values
0 commit comments