@@ -717,13 +717,23 @@ def __init__(
717
717
self .left_on = self .right_on = [cross_col ]
718
718
self ._cross = cross_col
719
719
720
- # note this function has side effects
721
720
(
722
721
self .left_join_keys ,
723
722
self .right_join_keys ,
724
723
self .join_names ,
724
+ left_drop ,
725
+ right_drop ,
725
726
) = self ._get_merge_keys ()
726
727
728
+ if left_drop :
729
+ self .left = self .left ._drop_labels_or_levels (left_drop )
730
+
731
+ if right_drop :
732
+ self .right = self .right ._drop_labels_or_levels (right_drop )
733
+
734
+ self ._maybe_require_matching_dtypes (self .left_join_keys , self .right_join_keys )
735
+ self ._validate_tolerance (self .left_join_keys )
736
+
727
737
# validate the merge keys dtypes. We may need to coerce
728
738
# to avoid incompatible dtypes
729
739
self ._maybe_coerce_merge_keys ()
@@ -732,7 +742,17 @@ def __init__(
732
742
# check if columns specified as unique
733
743
# are in fact unique.
734
744
if validate is not None :
735
- self ._validate (validate )
745
+ self ._validate_validate_kwd (validate )
746
+
747
+ def _maybe_require_matching_dtypes (
748
+ self , left_join_keys : list [ArrayLike ], right_join_keys : list [ArrayLike ]
749
+ ) -> None :
750
+ # Overridden by AsOfMerge
751
+ pass
752
+
753
+ def _validate_tolerance (self , left_join_keys : list [ArrayLike ]) -> None :
754
+ # Overridden by AsOfMerge
755
+ pass
736
756
737
757
@final
738
758
def _reindex_and_concat (
@@ -1127,24 +1147,21 @@ def _create_join_index(
1127
1147
index = index .append (Index ([fill_value ]))
1128
1148
return index .take (indexer )
1129
1149
1150
+ @final
1130
1151
def _get_merge_keys (
1131
1152
self ,
1132
- ) -> tuple [list [ArrayLike ], list [ArrayLike ], list [Hashable ]]:
1153
+ ) -> tuple [
1154
+ list [ArrayLike ],
1155
+ list [ArrayLike ],
1156
+ list [Hashable ],
1157
+ list [Hashable ],
1158
+ list [Hashable ],
1159
+ ]:
1133
1160
"""
1134
- Note: has side effects (copy/delete key columns)
1135
-
1136
- Parameters
1137
- ----------
1138
- left
1139
- right
1140
- on
1141
-
1142
1161
Returns
1143
1162
-------
1144
- left_keys, right_keys, join_names
1163
+ left_keys, right_keys, join_names, left_drop, right_drop
1145
1164
"""
1146
- # left_keys, right_keys entries can actually be anything listlike
1147
- # with a 'dtype' attr
1148
1165
left_keys : list [ArrayLike ] = []
1149
1166
right_keys : list [ArrayLike ] = []
1150
1167
join_names : list [Hashable ] = []
@@ -1264,13 +1281,7 @@ def _get_merge_keys(
1264
1281
else :
1265
1282
left_keys = [self .left .index ._values ]
1266
1283
1267
- if left_drop :
1268
- self .left = self .left ._drop_labels_or_levels (left_drop )
1269
-
1270
- if right_drop :
1271
- self .right = self .right ._drop_labels_or_levels (right_drop )
1272
-
1273
- return left_keys , right_keys , join_names
1284
+ return left_keys , right_keys , join_names , left_drop , right_drop
1274
1285
1275
1286
@final
1276
1287
def _maybe_coerce_merge_keys (self ) -> None :
@@ -1556,7 +1567,8 @@ def _validate_left_right_on(self, left_on, right_on):
1556
1567
1557
1568
return left_on , right_on
1558
1569
1559
- def _validate (self , validate : str ) -> None :
1570
+ @final
1571
+ def _validate_validate_kwd (self , validate : str ) -> None :
1560
1572
# Check uniqueness of each
1561
1573
if self .left_index :
1562
1574
left_unique = self .orig_left .index .is_unique
@@ -1811,19 +1823,14 @@ def __init__(
1811
1823
def get_result (self , copy : bool | None = True ) -> DataFrame :
1812
1824
join_index , left_indexer , right_indexer = self ._get_join_info ()
1813
1825
1814
- llabels , rlabels = _items_overlap_with_suffix (
1815
- self .left ._info_axis , self .right ._info_axis , self .suffixes
1816
- )
1817
-
1818
1826
left_join_indexer : npt .NDArray [np .intp ] | None
1819
1827
right_join_indexer : npt .NDArray [np .intp ] | None
1820
1828
1821
1829
if self .fill_method == "ffill" :
1822
1830
if left_indexer is None :
1823
1831
raise TypeError ("left_indexer cannot be None" )
1824
- left_indexer , right_indexer = cast (np .ndarray , left_indexer ), cast (
1825
- np .ndarray , right_indexer
1826
- )
1832
+ left_indexer = cast ("npt.NDArray[np.intp]" , left_indexer )
1833
+ right_indexer = cast ("npt.NDArray[np.intp]" , right_indexer )
1827
1834
left_join_indexer = libjoin .ffill_indexer (left_indexer )
1828
1835
right_join_indexer = libjoin .ffill_indexer (right_indexer )
1829
1836
else :
@@ -1888,6 +1895,18 @@ def __init__(
1888
1895
self .allow_exact_matches = allow_exact_matches
1889
1896
self .direction = direction
1890
1897
1898
+ # check 'direction' is valid
1899
+ if self .direction not in ["backward" , "forward" , "nearest" ]:
1900
+ raise MergeError (f"direction invalid: { self .direction } " )
1901
+
1902
+ # validate allow_exact_matches
1903
+ if not is_bool (self .allow_exact_matches ):
1904
+ msg = (
1905
+ "allow_exact_matches must be boolean, "
1906
+ f"passed { self .allow_exact_matches } "
1907
+ )
1908
+ raise MergeError (msg )
1909
+
1891
1910
_OrderedMerge .__init__ (
1892
1911
self ,
1893
1912
left ,
@@ -1975,17 +1994,12 @@ def _validate_left_right_on(self, left_on, right_on):
1975
1994
left_on = self .left_by + list (left_on )
1976
1995
right_on = self .right_by + list (right_on )
1977
1996
1978
- # check 'direction' is valid
1979
- if self .direction not in ["backward" , "forward" , "nearest" ]:
1980
- raise MergeError (f"direction invalid: { self .direction } " )
1981
-
1982
1997
return left_on , right_on
1983
1998
1984
- def _get_merge_keys (
1985
- self ,
1986
- ) -> tuple [list [ArrayLike ], list [ArrayLike ], list [Hashable ]]:
1987
- # note this function has side effects
1988
- (left_join_keys , right_join_keys , join_names ) = super ()._get_merge_keys ()
1999
+ def _maybe_require_matching_dtypes (
2000
+ self , left_join_keys : list [ArrayLike ], right_join_keys : list [ArrayLike ]
2001
+ ) -> None :
2002
+ # TODO: why do we do this for AsOfMerge but not the others?
1989
2003
1990
2004
# validate index types are the same
1991
2005
for i , (lk , rk ) in enumerate (zip (left_join_keys , right_join_keys )):
@@ -2012,6 +2026,7 @@ def _get_merge_keys(
2012
2026
)
2013
2027
raise MergeError (msg )
2014
2028
2029
+ def _validate_tolerance (self , left_join_keys : list [ArrayLike ]) -> None :
2015
2030
# validate tolerance; datetime.timedelta or Timedelta if we have a DTI
2016
2031
if self .tolerance is not None :
2017
2032
if self .left_index :
@@ -2046,16 +2061,6 @@ def _get_merge_keys(
2046
2061
else :
2047
2062
raise MergeError ("key must be integer, timestamp or float" )
2048
2063
2049
- # validate allow_exact_matches
2050
- if not is_bool (self .allow_exact_matches ):
2051
- msg = (
2052
- "allow_exact_matches must be boolean, "
2053
- f"passed { self .allow_exact_matches } "
2054
- )
2055
- raise MergeError (msg )
2056
-
2057
- return left_join_keys , right_join_keys , join_names
2058
-
2059
2064
def _get_join_indexers (self ) -> tuple [npt .NDArray [np .intp ], npt .NDArray [np .intp ]]:
2060
2065
"""return the join indexers"""
2061
2066
0 commit comments