40
40
from pandas .core .dtypes .missing import isna , na_value_for_dtype , notna
41
41
42
42
import pandas .core .algorithms as algos
43
+ from pandas .core .arraylike import OpsMixin
43
44
from pandas .core .arrays import ExtensionArray , ExtensionOpsMixin
44
45
from pandas .core .arrays .sparse .dtype import SparseDtype
45
46
from pandas .core .base import PandasObject
@@ -195,7 +196,7 @@ def _wrap_result(name, data, sparse_index, fill_value, dtype=None):
195
196
)
196
197
197
198
198
- class SparseArray (PandasObject , ExtensionArray , ExtensionOpsMixin ):
199
+ class SparseArray (OpsMixin , PandasObject , ExtensionArray , ExtensionOpsMixin ):
199
200
"""
200
201
An ExtensionArray for storing sparse data.
201
202
@@ -762,8 +763,6 @@ def value_counts(self, dropna=True):
762
763
# --------
763
764
764
765
def __getitem__ (self , key ):
765
- # avoid mypy issues when importing at the top-level
766
- from pandas .core .indexing import check_bool_indexer
767
766
768
767
if isinstance (key , tuple ):
769
768
if len (key ) > 1 :
@@ -796,7 +795,6 @@ def __getitem__(self, key):
796
795
key = check_array_indexer (self , key )
797
796
798
797
if com .is_bool_indexer (key ):
799
- key = check_bool_indexer (self , key )
800
798
801
799
return self .take (np .arange (len (key ), dtype = np .int32 )[key ])
802
800
elif hasattr (key , "__len__" ):
@@ -1390,17 +1388,6 @@ def __abs__(self):
1390
1388
# Ops
1391
1389
# ------------------------------------------------------------------------
1392
1390
1393
- @classmethod
1394
- def _create_unary_method (cls , op ) -> Callable [["SparseArray" ], "SparseArray" ]:
1395
- def sparse_unary_method (self ) -> "SparseArray" :
1396
- fill_value = op (np .array (self .fill_value )).item ()
1397
- values = op (self .sp_values )
1398
- dtype = SparseDtype (values .dtype , fill_value )
1399
- return cls ._simple_new (values , self .sp_index , dtype )
1400
-
1401
- name = f"__{ op .__name__ } __"
1402
- return compat .set_function_name (sparse_unary_method , name , cls )
1403
-
1404
1391
@classmethod
1405
1392
def _create_arithmetic_method (cls , op ):
1406
1393
op_name = op .__name__
@@ -1444,56 +1431,48 @@ def sparse_arithmetic_method(self, other):
1444
1431
name = f"__{ op .__name__ } __"
1445
1432
return compat .set_function_name (sparse_arithmetic_method , name , cls )
1446
1433
1447
- @classmethod
1448
- def _create_comparison_method (cls , op ):
1449
- op_name = op .__name__
1450
- if op_name in {"and_" , "or_" }:
1451
- op_name = op_name [:- 1 ]
1434
+ def _cmp_method (self , other , op ) -> "SparseArray" :
1435
+ if not is_scalar (other ) and not isinstance (other , type (self )):
1436
+ # convert list-like to ndarray
1437
+ other = np .asarray (other )
1452
1438
1453
- @unpack_zerodim_and_defer (op_name )
1454
- def cmp_method (self , other ):
1455
-
1456
- if not is_scalar (other ) and not isinstance (other , type (self )):
1457
- # convert list-like to ndarray
1458
- other = np .asarray (other )
1439
+ if isinstance (other , np .ndarray ):
1440
+ # TODO: make this more flexible than just ndarray...
1441
+ if len (self ) != len (other ):
1442
+ raise AssertionError (f"length mismatch: { len (self )} vs. { len (other )} " )
1443
+ other = SparseArray (other , fill_value = self .fill_value )
1459
1444
1460
- if isinstance (other , np .ndarray ):
1461
- # TODO: make this more flexible than just ndarray...
1462
- if len (self ) != len (other ):
1463
- raise AssertionError (
1464
- f"length mismatch: { len (self )} vs. { len (other )} "
1465
- )
1466
- other = SparseArray (other , fill_value = self .fill_value )
1445
+ if isinstance (other , SparseArray ):
1446
+ op_name = op .__name__ .strip ("_" )
1447
+ return _sparse_array_op (self , other , op , op_name )
1448
+ else :
1449
+ with np .errstate (all = "ignore" ):
1450
+ fill_value = op (self .fill_value , other )
1451
+ result = op (self .sp_values , other )
1452
+
1453
+ return type (self )(
1454
+ result ,
1455
+ sparse_index = self .sp_index ,
1456
+ fill_value = fill_value ,
1457
+ dtype = np .bool_ ,
1458
+ )
1467
1459
1468
- if isinstance (other , SparseArray ):
1469
- return _sparse_array_op (self , other , op , op_name )
1470
- else :
1471
- with np .errstate (all = "ignore" ):
1472
- fill_value = op (self .fill_value , other )
1473
- result = op (self .sp_values , other )
1460
+ _logical_method = _cmp_method
1474
1461
1475
- return type (self )(
1476
- result ,
1477
- sparse_index = self .sp_index ,
1478
- fill_value = fill_value ,
1479
- dtype = np .bool_ ,
1480
- )
1462
+ def _unary_method (self , op ) -> "SparseArray" :
1463
+ fill_value = op (np .array (self .fill_value )).item ()
1464
+ values = op (self .sp_values )
1465
+ dtype = SparseDtype (values .dtype , fill_value )
1466
+ return type (self )._simple_new (values , self .sp_index , dtype )
1481
1467
1482
- name = f"__ { op . __name__ } __"
1483
- return compat . set_function_name ( cmp_method , name , cls )
1468
+ def __pos__ ( self ) -> "SparseArray" :
1469
+ return self . _unary_method ( operator . pos )
1484
1470
1485
- @classmethod
1486
- def _add_unary_ops (cls ):
1487
- cls .__pos__ = cls ._create_unary_method (operator .pos )
1488
- cls .__neg__ = cls ._create_unary_method (operator .neg )
1489
- cls .__invert__ = cls ._create_unary_method (operator .invert )
1471
+ def __neg__ (self ) -> "SparseArray" :
1472
+ return self ._unary_method (operator .neg )
1490
1473
1491
- @classmethod
1492
- def _add_comparison_ops (cls ):
1493
- cls .__and__ = cls ._create_comparison_method (operator .and_ )
1494
- cls .__or__ = cls ._create_comparison_method (operator .or_ )
1495
- cls .__xor__ = cls ._create_arithmetic_method (operator .xor )
1496
- super ()._add_comparison_ops ()
1474
+ def __invert__ (self ) -> "SparseArray" :
1475
+ return self ._unary_method (operator .invert )
1497
1476
1498
1477
# ----------
1499
1478
# Formatting
@@ -1511,8 +1490,6 @@ def _formatter(self, boxed=False):
1511
1490
1512
1491
1513
1492
SparseArray ._add_arithmetic_ops ()
1514
- SparseArray ._add_comparison_ops ()
1515
- SparseArray ._add_unary_ops ()
1516
1493
1517
1494
1518
1495
def make_sparse (arr : np .ndarray , kind = "block" , fill_value = None , dtype = None ):
0 commit comments