43
43
is_bool_dtype ,
44
44
is_datetime64_dtype ,
45
45
is_dtype_equal ,
46
- is_float ,
47
46
is_float_dtype ,
48
47
is_integer_dtype ,
49
48
is_list_like ,
50
- is_numeric_dtype ,
51
49
is_object_dtype ,
52
50
is_scalar ,
53
51
is_string_dtype ,
@@ -327,9 +325,53 @@ def ravel(self: BaseMaskedArrayT, *args, **kwargs) -> BaseMaskedArrayT:
327
325
def T (self : BaseMaskedArrayT ) -> BaseMaskedArrayT :
328
326
return type (self )(self ._data .T , self ._mask .T )
329
327
328
+ def round (self , decimals : int = 0 , * args , ** kwargs ):
329
+ """
330
+ Round each value in the array a to the given number of decimals.
331
+
332
+ Parameters
333
+ ----------
334
+ decimals : int, default 0
335
+ Number of decimal places to round to. If decimals is negative,
336
+ it specifies the number of positions to the left of the decimal point.
337
+ *args, **kwargs
338
+ Additional arguments and keywords have no effect but might be
339
+ accepted for compatibility with NumPy.
340
+
341
+ Returns
342
+ -------
343
+ NumericArray
344
+ Rounded values of the NumericArray.
345
+
346
+ See Also
347
+ --------
348
+ numpy.around : Round values of an np.array.
349
+ DataFrame.round : Round values of a DataFrame.
350
+ Series.round : Round values of a Series.
351
+ """
352
+ nv .validate_round (args , kwargs )
353
+ values = np .round (self ._data , decimals = decimals , ** kwargs )
354
+
355
+ # Usually we'll get same type as self, but ndarray[bool] casts to float
356
+ return self ._maybe_mask_result (values , self ._mask .copy ())
357
+
358
+ # ------------------------------------------------------------------
359
+ # Unary Methods
360
+
330
361
def __invert__ (self : BaseMaskedArrayT ) -> BaseMaskedArrayT :
331
362
return type (self )(~ self ._data , self ._mask .copy ())
332
363
364
+ def __neg__ (self ):
365
+ return type (self )(- self ._data , self ._mask .copy ())
366
+
367
+ def __pos__ (self ):
368
+ return self .copy ()
369
+
370
+ def __abs__ (self ):
371
+ return type (self )(abs (self ._data ), self ._mask .copy ())
372
+
373
+ # ------------------------------------------------------------------
374
+
333
375
def to_numpy (
334
376
self ,
335
377
dtype : npt .DTypeLike | None = None ,
@@ -671,7 +713,7 @@ def _arith_method(self, other, op):
671
713
# x ** 0 is 1.
672
714
mask = np .where ((self ._data == 0 ) & ~ self ._mask , False , mask )
673
715
674
- return self ._maybe_mask_result (result , mask , other , op_name )
716
+ return self ._maybe_mask_result (result , mask )
675
717
676
718
def _cmp_method (self , other , op ) -> BooleanArray :
677
719
from pandas .core .arrays import BooleanArray
@@ -713,36 +755,27 @@ def _cmp_method(self, other, op) -> BooleanArray:
713
755
mask = self ._propagate_mask (mask , other )
714
756
return BooleanArray (result , mask , copy = False )
715
757
716
- def _maybe_mask_result (self , result , mask , other , op_name : str ):
758
+ def _maybe_mask_result (self , result , mask ):
717
759
"""
718
760
Parameters
719
761
----------
720
- result : array-like
762
+ result : array-like or tuple[array-like]
721
763
mask : array-like bool
722
- other : scalar or array-like
723
- op_name : str
724
764
"""
725
- if op_name == "divmod" :
726
- # divmod returns a tuple
765
+ if isinstance ( result , tuple ) :
766
+ # i.e. divmod
727
767
div , mod = result
728
768
return (
729
- self ._maybe_mask_result (div , mask , other , "floordiv" ),
730
- self ._maybe_mask_result (mod , mask , other , "mod" ),
769
+ self ._maybe_mask_result (div , mask ),
770
+ self ._maybe_mask_result (mod , mask ),
731
771
)
732
772
733
- # if we have a float operand we are by-definition
734
- # a float result
735
- # or our op is a divide
736
- if (
737
- (is_float_dtype (other ) or is_float (other ))
738
- or (op_name in ["rtruediv" , "truediv" ])
739
- or (is_float_dtype (self .dtype ) and is_numeric_dtype (result .dtype ))
740
- ):
773
+ if is_float_dtype (result .dtype ):
741
774
from pandas .core .arrays import FloatingArray
742
775
743
776
return FloatingArray (result , mask , copy = False )
744
777
745
- elif is_bool_dtype (result ):
778
+ elif is_bool_dtype (result . dtype ):
746
779
from pandas .core .arrays import BooleanArray
747
780
748
781
return BooleanArray (result , mask , copy = False )
@@ -757,7 +790,7 @@ def _maybe_mask_result(self, result, mask, other, op_name: str):
757
790
result [mask ] = result .dtype .type ("NaT" )
758
791
return result
759
792
760
- elif is_integer_dtype (result ):
793
+ elif is_integer_dtype (result . dtype ):
761
794
from pandas .core .arrays import IntegerArray
762
795
763
796
return IntegerArray (result , mask , copy = False )
@@ -980,6 +1013,9 @@ def _quantile(
980
1013
out = np .asarray (res , dtype = np .float64 ) # type: ignore[assignment]
981
1014
return out
982
1015
1016
+ # ------------------------------------------------------------------
1017
+ # Reductions
1018
+
983
1019
def _reduce (self , name : str , * , skipna : bool = True , ** kwargs ):
984
1020
if name in {"any" , "all" , "min" , "max" , "sum" , "prod" }:
985
1021
return getattr (self , name )(skipna = skipna , ** kwargs )
@@ -1015,7 +1051,7 @@ def _wrap_reduction_result(self, name: str, result, skipna, **kwargs):
1015
1051
else :
1016
1052
mask = self ._mask .any (axis = axis )
1017
1053
1018
- return self ._maybe_mask_result (result , mask , other = None , op_name = name )
1054
+ return self ._maybe_mask_result (result , mask )
1019
1055
return result
1020
1056
1021
1057
def sum (self , * , skipna = True , min_count = 0 , axis : int | None = 0 , ** kwargs ):
0 commit comments