13
13
from pandas .errors import NullFrequencyError
14
14
from pandas .util ._decorators import Appender
15
15
16
- from pandas .core .dtypes .cast import (
17
- construct_1d_object_array_from_listlike ,
18
- find_common_type ,
19
- maybe_upcast_putmask ,
20
- )
16
+ from pandas .core .dtypes .cast import construct_1d_object_array_from_listlike
21
17
from pandas .core .dtypes .common import (
22
18
ensure_object ,
23
19
is_bool_dtype ,
29
25
is_integer_dtype ,
30
26
is_list_like ,
31
27
is_object_dtype ,
32
- is_period_dtype ,
33
28
is_scalar ,
34
29
is_timedelta64_dtype ,
35
30
)
36
31
from pandas .core .dtypes .generic import (
37
32
ABCDataFrame ,
38
33
ABCDatetimeArray ,
39
34
ABCDatetimeIndex ,
40
- ABCIndex ,
41
35
ABCIndexClass ,
42
36
ABCSeries ,
43
37
ABCSparseSeries ,
47
41
import pandas as pd
48
42
from pandas ._typing import ArrayLike
49
43
from pandas .core .construction import array , extract_array
50
- from pandas .core .ops import missing
44
+ from pandas .core .ops . array_ops import comp_method_OBJECT_ARRAY , define_na_arithmetic_op
51
45
from pandas .core .ops .docstrings import (
52
46
_arith_doc_FRAME ,
53
47
_flex_comp_doc_FRAME ,
@@ -398,63 +392,6 @@ def mask_cmp_op(x, y, op):
398
392
return result
399
393
400
394
401
- def masked_arith_op (x , y , op ):
402
- """
403
- If the given arithmetic operation fails, attempt it again on
404
- only the non-null elements of the input array(s).
405
-
406
- Parameters
407
- ----------
408
- x : np.ndarray
409
- y : np.ndarray, Series, Index
410
- op : binary operator
411
- """
412
- # For Series `x` is 1D so ravel() is a no-op; calling it anyway makes
413
- # the logic valid for both Series and DataFrame ops.
414
- xrav = x .ravel ()
415
- assert isinstance (x , np .ndarray ), type (x )
416
- if isinstance (y , np .ndarray ):
417
- dtype = find_common_type ([x .dtype , y .dtype ])
418
- result = np .empty (x .size , dtype = dtype )
419
-
420
- # PeriodIndex.ravel() returns int64 dtype, so we have
421
- # to work around that case. See GH#19956
422
- yrav = y if is_period_dtype (y ) else y .ravel ()
423
- mask = notna (xrav ) & notna (yrav )
424
-
425
- if yrav .shape != mask .shape :
426
- # FIXME: GH#5284, GH#5035, GH#19448
427
- # Without specifically raising here we get mismatched
428
- # errors in Py3 (TypeError) vs Py2 (ValueError)
429
- # Note: Only = an issue in DataFrame case
430
- raise ValueError ("Cannot broadcast operands together." )
431
-
432
- if mask .any ():
433
- with np .errstate (all = "ignore" ):
434
- result [mask ] = op (xrav [mask ], yrav [mask ])
435
-
436
- else :
437
- assert is_scalar (y ), type (y )
438
- assert isinstance (x , np .ndarray ), type (x )
439
- # mask is only meaningful for x
440
- result = np .empty (x .size , dtype = x .dtype )
441
- mask = notna (xrav )
442
-
443
- # 1 ** np.nan is 1. So we have to unmask those.
444
- if op == pow :
445
- mask = np .where (x == 1 , False , mask )
446
- elif op == rpow :
447
- mask = np .where (y == 1 , False , mask )
448
-
449
- if mask .any ():
450
- with np .errstate (all = "ignore" ):
451
- result [mask ] = op (xrav [mask ], y )
452
-
453
- result , changed = maybe_upcast_putmask (result , ~ mask , np .nan )
454
- result = result .reshape (x .shape ) # 2D compat
455
- return result
456
-
457
-
458
395
# -----------------------------------------------------------------------------
459
396
# Dispatch logic
460
397
@@ -673,33 +610,7 @@ def _arith_method_SERIES(cls, op, special):
673
610
_construct_divmod_result if op in [divmod , rdivmod ] else _construct_result
674
611
)
675
612
676
- def na_op (x , y ):
677
- """
678
- Return the result of evaluating op on the passed in values.
679
-
680
- If native types are not compatible, try coersion to object dtype.
681
-
682
- Parameters
683
- ----------
684
- x : array-like
685
- y : array-like or scalar
686
-
687
- Returns
688
- -------
689
- array-like
690
-
691
- Raises
692
- ------
693
- TypeError : invalid operation
694
- """
695
- import pandas .core .computation .expressions as expressions
696
-
697
- try :
698
- result = expressions .evaluate (op , str_rep , x , y , ** eval_kwargs )
699
- except TypeError :
700
- result = masked_arith_op (x , y , op )
701
-
702
- return missing .dispatch_fill_zeros (op , x , y , result )
613
+ na_op = define_na_arithmetic_op (op , str_rep , eval_kwargs )
703
614
704
615
def wrapper (left , right ):
705
616
if isinstance (right , ABCDataFrame ):
@@ -735,22 +646,6 @@ def wrapper(left, right):
735
646
return wrapper
736
647
737
648
738
- def _comp_method_OBJECT_ARRAY (op , x , y ):
739
- if isinstance (y , list ):
740
- y = construct_1d_object_array_from_listlike (y )
741
- if isinstance (y , (np .ndarray , ABCSeries , ABCIndex )):
742
- if not is_object_dtype (y .dtype ):
743
- y = y .astype (np .object_ )
744
-
745
- if isinstance (y , (ABCSeries , ABCIndex )):
746
- y = y .values
747
-
748
- result = libops .vec_compare (x , y , op )
749
- else :
750
- result = libops .scalar_compare (x , y , op )
751
- return result
752
-
753
-
754
649
def _comp_method_SERIES (cls , op , special ):
755
650
"""
756
651
Wrapper function for Series arithmetic operations, to avoid
@@ -764,7 +659,7 @@ def na_op(x, y):
764
659
# Extension Dtypes are not called here
765
660
766
661
if is_object_dtype (x .dtype ):
767
- result = _comp_method_OBJECT_ARRAY (op , x , y )
662
+ result = comp_method_OBJECT_ARRAY (op , x , y )
768
663
769
664
elif is_datetimelike_v_numeric (x , y ):
770
665
return invalid_comparison (x , y , op )
@@ -1091,15 +986,7 @@ def _arith_method_FRAME(cls, op, special):
1091
986
eval_kwargs = _gen_eval_kwargs (op_name )
1092
987
default_axis = _get_frame_op_default_axis (op_name )
1093
988
1094
- def na_op (x , y ):
1095
- import pandas .core .computation .expressions as expressions
1096
-
1097
- try :
1098
- result = expressions .evaluate (op , str_rep , x , y , ** eval_kwargs )
1099
- except TypeError :
1100
- result = masked_arith_op (x , y , op )
1101
-
1102
- return missing .dispatch_fill_zeros (op , x , y , result )
989
+ na_op = define_na_arithmetic_op (op , str_rep , eval_kwargs )
1103
990
1104
991
if op_name in _op_descriptions :
1105
992
# i.e. include "add" but not "__add__"
0 commit comments