8
8
Callable ,
9
9
Hashable ,
10
10
Literal ,
11
- TypeVar ,
12
11
)
13
12
14
13
import numpy as np
23
22
AxisInt ,
24
23
DtypeObj ,
25
24
QuantileInterpolation ,
25
+ Self ,
26
26
npt ,
27
27
)
28
28
from pandas .util ._validators import validate_bool_kwarg
93
93
to_native_types ,
94
94
)
95
95
96
- T = TypeVar ("T" , bound = "BaseArrayManager" )
97
-
98
96
99
97
class BaseArrayManager (DataManager ):
100
98
"""
@@ -129,7 +127,7 @@ def __init__(
129
127
) -> None :
130
128
raise NotImplementedError
131
129
132
- def make_empty (self : T , axes = None ) -> T :
130
+ def make_empty (self , axes = None ) -> Self :
133
131
"""Return an empty ArrayManager with the items axis of len 0 (no columns)"""
134
132
if axes is None :
135
133
axes = [self .axes [1 :], Index ([])]
@@ -193,11 +191,11 @@ def __repr__(self) -> str:
193
191
return output
194
192
195
193
def apply (
196
- self : T ,
194
+ self ,
197
195
f ,
198
196
align_keys : list [str ] | None = None ,
199
197
** kwargs ,
200
- ) -> T :
198
+ ) -> Self :
201
199
"""
202
200
Iterate over the arrays, collect and create a new ArrayManager.
203
201
@@ -255,8 +253,8 @@ def apply(
255
253
return type (self )(result_arrays , new_axes ) # type: ignore[arg-type]
256
254
257
255
def apply_with_block (
258
- self : T , f , align_keys = None , swap_axis : bool = True , ** kwargs
259
- ) -> T :
256
+ self , f , align_keys = None , swap_axis : bool = True , ** kwargs
257
+ ) -> Self :
260
258
# switch axis to follow BlockManager logic
261
259
if swap_axis and "axis" in kwargs and self .ndim == 2 :
262
260
kwargs ["axis" ] = 1 if kwargs ["axis" ] == 0 else 0
@@ -309,7 +307,7 @@ def apply_with_block(
309
307
310
308
return type (self )(result_arrays , self ._axes )
311
309
312
- def where (self : T , other , cond , align : bool ) -> T :
310
+ def where (self , other , cond , align : bool ) -> Self :
313
311
if align :
314
312
align_keys = ["other" , "cond" ]
315
313
else :
@@ -323,10 +321,10 @@ def where(self: T, other, cond, align: bool) -> T:
323
321
cond = cond ,
324
322
)
325
323
326
- def setitem (self : T , indexer , value ) -> T :
324
+ def setitem (self , indexer , value ) -> Self :
327
325
return self .apply_with_block ("setitem" , indexer = indexer , value = value )
328
326
329
- def putmask (self : T , mask , new , align : bool = True ) -> T :
327
+ def putmask (self , mask , new , align : bool = True ) -> Self :
330
328
if align :
331
329
align_keys = ["new" , "mask" ]
332
330
else :
@@ -340,14 +338,14 @@ def putmask(self: T, mask, new, align: bool = True) -> T:
340
338
new = new ,
341
339
)
342
340
343
- def diff (self : T , n : int , axis : AxisInt ) -> T :
341
+ def diff (self , n : int , axis : AxisInt ) -> Self :
344
342
assert self .ndim == 2 and axis == 0 # caller ensures
345
343
return self .apply (algos .diff , n = n , axis = axis )
346
344
347
- def interpolate (self : T , ** kwargs ) -> T :
345
+ def interpolate (self , ** kwargs ) -> Self :
348
346
return self .apply_with_block ("interpolate" , swap_axis = False , ** kwargs )
349
347
350
- def shift (self : T , periods : int , axis : AxisInt , fill_value ) -> T :
348
+ def shift (self , periods : int , axis : AxisInt , fill_value ) -> Self :
351
349
if fill_value is lib .no_default :
352
350
fill_value = None
353
351
@@ -359,7 +357,7 @@ def shift(self: T, periods: int, axis: AxisInt, fill_value) -> T:
359
357
"shift" , periods = periods , axis = axis , fill_value = fill_value
360
358
)
361
359
362
- def fillna (self : T , value , limit , inplace : bool , downcast ) -> T :
360
+ def fillna (self , value , limit , inplace : bool , downcast ) -> Self :
363
361
if limit is not None :
364
362
# Do this validation even if we go through one of the no-op paths
365
363
limit = libalgos .validate_limit (None , limit = limit )
@@ -368,13 +366,13 @@ def fillna(self: T, value, limit, inplace: bool, downcast) -> T:
368
366
"fillna" , value = value , limit = limit , inplace = inplace , downcast = downcast
369
367
)
370
368
371
- def astype (self : T , dtype , copy : bool | None = False , errors : str = "raise" ) -> T :
369
+ def astype (self , dtype , copy : bool | None = False , errors : str = "raise" ) -> Self :
372
370
if copy is None :
373
371
copy = True
374
372
375
373
return self .apply (astype_array_safe , dtype = dtype , copy = copy , errors = errors )
376
374
377
- def convert (self : T , copy : bool | None ) -> T :
375
+ def convert (self , copy : bool | None ) -> Self :
378
376
if copy is None :
379
377
copy = True
380
378
@@ -397,10 +395,10 @@ def _convert(arr):
397
395
398
396
return self .apply (_convert )
399
397
400
- def replace_regex (self : T , ** kwargs ) -> T :
398
+ def replace_regex (self , ** kwargs ) -> Self :
401
399
return self .apply_with_block ("_replace_regex" , ** kwargs )
402
400
403
- def replace (self : T , to_replace , value , inplace : bool ) -> T :
401
+ def replace (self , to_replace , value , inplace : bool ) -> Self :
404
402
inplace = validate_bool_kwarg (inplace , "inplace" )
405
403
assert np .ndim (value ) == 0 , value
406
404
# TODO "replace" is right now implemented on the blocks, we should move
@@ -410,12 +408,12 @@ def replace(self: T, to_replace, value, inplace: bool) -> T:
410
408
)
411
409
412
410
def replace_list (
413
- self : T ,
411
+ self ,
414
412
src_list : list [Any ],
415
413
dest_list : list [Any ],
416
414
inplace : bool = False ,
417
415
regex : bool = False ,
418
- ) -> T :
416
+ ) -> Self :
419
417
"""do a list replace"""
420
418
inplace = validate_bool_kwarg (inplace , "inplace" )
421
419
@@ -427,7 +425,7 @@ def replace_list(
427
425
regex = regex ,
428
426
)
429
427
430
- def to_native_types (self : T , ** kwargs ) -> T :
428
+ def to_native_types (self , ** kwargs ) -> Self :
431
429
return self .apply (to_native_types , ** kwargs )
432
430
433
431
@property
@@ -453,7 +451,7 @@ def is_view(self) -> bool:
453
451
def is_single_block (self ) -> bool :
454
452
return len (self .arrays ) == 1
455
453
456
- def _get_data_subset (self : T , predicate : Callable ) -> T :
454
+ def _get_data_subset (self , predicate : Callable ) -> Self :
457
455
indices = [i for i , arr in enumerate (self .arrays ) if predicate (arr )]
458
456
arrays = [self .arrays [i ] for i in indices ]
459
457
# TODO copy?
@@ -464,7 +462,7 @@ def _get_data_subset(self: T, predicate: Callable) -> T:
464
462
new_axes = [self ._axes [0 ], new_cols ]
465
463
return type (self )(arrays , new_axes , verify_integrity = False )
466
464
467
- def get_bool_data (self : T , copy : bool = False ) -> T :
465
+ def get_bool_data (self , copy : bool = False ) -> Self :
468
466
"""
469
467
Select columns that are bool-dtype and object-dtype columns that are all-bool.
470
468
@@ -475,7 +473,7 @@ def get_bool_data(self: T, copy: bool = False) -> T:
475
473
"""
476
474
return self ._get_data_subset (lambda x : x .dtype == np .dtype (bool ))
477
475
478
- def get_numeric_data (self : T , copy : bool = False ) -> T :
476
+ def get_numeric_data (self , copy : bool = False ) -> Self :
479
477
"""
480
478
Select columns that have a numeric dtype.
481
479
@@ -489,7 +487,7 @@ def get_numeric_data(self: T, copy: bool = False) -> T:
489
487
or getattr (arr .dtype , "_is_numeric" , False )
490
488
)
491
489
492
- def copy (self : T , deep : bool | Literal ["all" ] | None = True ) -> T :
490
+ def copy (self , deep : bool | Literal ["all" ] | None = True ) -> Self :
493
491
"""
494
492
Make deep or shallow copy of ArrayManager
495
493
@@ -526,7 +524,7 @@ def copy_func(ax):
526
524
return type (self )(new_arrays , new_axes , verify_integrity = False )
527
525
528
526
def reindex_indexer (
529
- self : T ,
527
+ self ,
530
528
new_axis ,
531
529
indexer ,
532
530
axis : AxisInt ,
@@ -537,7 +535,7 @@ def reindex_indexer(
537
535
only_slice : bool = False ,
538
536
# ArrayManager specific keywords
539
537
use_na_proxy : bool = False ,
540
- ) -> T :
538
+ ) -> Self :
541
539
axis = self ._normalize_axis (axis )
542
540
return self ._reindex_indexer (
543
541
new_axis ,
@@ -550,15 +548,15 @@ def reindex_indexer(
550
548
)
551
549
552
550
def _reindex_indexer (
553
- self : T ,
551
+ self ,
554
552
new_axis ,
555
553
indexer : npt .NDArray [np .intp ] | None ,
556
554
axis : AxisInt ,
557
555
fill_value = None ,
558
556
allow_dups : bool = False ,
559
557
copy : bool | None = True ,
560
558
use_na_proxy : bool = False ,
561
- ) -> T :
559
+ ) -> Self :
562
560
"""
563
561
Parameters
564
562
----------
@@ -629,12 +627,12 @@ def _reindex_indexer(
629
627
return type (self )(new_arrays , new_axes , verify_integrity = False )
630
628
631
629
def take (
632
- self : T ,
630
+ self ,
633
631
indexer : npt .NDArray [np .intp ],
634
632
axis : AxisInt = 1 ,
635
633
verify : bool = True ,
636
634
convert_indices : bool = True ,
637
- ) -> T :
635
+ ) -> Self :
638
636
"""
639
637
Take items along any axis.
640
638
"""
@@ -923,7 +921,7 @@ def idelete(self, indexer) -> ArrayManager:
923
921
# --------------------------------------------------------------------
924
922
# Array-wise Operation
925
923
926
- def grouped_reduce (self : T , func : Callable ) -> T :
924
+ def grouped_reduce (self , func : Callable ) -> Self :
927
925
"""
928
926
Apply grouped reduction function columnwise, returning a new ArrayManager.
929
927
@@ -962,7 +960,7 @@ def grouped_reduce(self: T, func: Callable) -> T:
962
960
# expected "List[Union[ndarray, ExtensionArray]]"
963
961
return type (self )(result_arrays , [index , columns ]) # type: ignore[arg-type]
964
962
965
- def reduce (self : T , func : Callable ) -> T :
963
+ def reduce (self , func : Callable ) -> Self :
966
964
"""
967
965
Apply reduction function column-wise, returning a single-row ArrayManager.
968
966
0 commit comments