Repository: pandas-dev/pandas

Issue:
merge_asof doesn't allow float tolerance for float merges
The merge_asof function allows you to merge on float values but doesn't allow tolerance value when performing this merge, unlike for integer and datetime merges. I'm currently working on a pull request to fix this by removing the error being thrown for non-integer numerical tolerances.

```python
left = pd.DataFrame({'a': [1.1, 3.5, 10.9],
                     'left_val': ['a', 'b', 'c']})

right = pd.DataFrame({'a': [1.0, 2.5, 3.3, 7.5, 11.5],
                      'right_val': [1.0, 2.5, 3.3, 7.5, 11.5]})

expected = pd.DataFrame({'a': [1.1, 3.5, 10.9],
                         'left_val': ['a', 'b', 'c'],
                         'right_val': [1, 3.3, np.nan]})

result = pd.merge_asof(left, right, on='a', direction='nearest',
                       tolerance=0.5)

MergeError: key must be integer or timestamp
```

Expected output:

```
     a left_val  right_val
0   1.1        a        1.0
1   3.5        b        3.3
2  10.9        c        NaN
```


Discussion:

Resolving patch:
diff --git a/pandas/core/reshape/merge.py b/pandas/core/reshape/merge.py
--- a/pandas/core/reshape/merge.py
+++ b/pandas/core/reshape/merge.py
@@ -23,6 +23,7 @@
     is_categorical_dtype,
     is_integer_dtype,
     is_float_dtype,
+    is_number,
     is_numeric_dtype,
     is_integer,
     is_int_or_datetime_dtype,
@@ -1356,8 +1357,14 @@ def _get_merge_keys(self):
                 if self.tolerance < 0:
                     raise MergeError("tolerance must be positive")
 
+            elif is_float_dtype(lt):
+                if not is_number(self.tolerance):
+                    raise MergeError(msg)
+                if self.tolerance < 0:
+                    raise MergeError("tolerance must be positive")
+
             else:
-                raise MergeError("key must be integer or timestamp")
+                raise MergeError("key must be integer, timestamp or float")
 
         # validate allow_exact_matches
         if not is_bool(self.allow_exact_matches):


Test patch:
diff --git a/pandas/tests/reshape/merge/test_merge_asof.py b/pandas/tests/reshape/merge/test_merge_asof.py
--- a/pandas/tests/reshape/merge/test_merge_asof.py
+++ b/pandas/tests/reshape/merge/test_merge_asof.py
@@ -642,6 +642,21 @@ def test_tolerance_tz(self):
              'value2': list("BCDEE")})
         assert_frame_equal(result, expected)
 
+    def test_tolerance_float(self):
+        # GH22981
+        left = pd.DataFrame({'a': [1.1, 3.5, 10.9],
+                             'left_val': ['a', 'b', 'c']})
+        right = pd.DataFrame({'a': [1.0, 2.5, 3.3, 7.5, 11.5],
+                              'right_val': [1.0, 2.5, 3.3, 7.5, 11.5]})
+
+        expected = pd.DataFrame({'a': [1.1, 3.5, 10.9],
+                                 'left_val': ['a', 'b', 'c'],
+                                 'right_val': [1, 3.3, np.nan]})
+
+        result = pd.merge_asof(left, right, on='a', direction='nearest',
+                               tolerance=0.5)
+        assert_frame_equal(result, expected)
+
     def test_index_tolerance(self):
         # GH 15135
         expected = self.tolerance.set_index('time')