We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Value error using sjoin with pandas v0.23
I use the `sjoin` function to add the region name (polygons) to every point within the region. Some points are not in any region, therefore I filter these points and buffer them step by step. So the points layer without intersection becomes smaller and smaller. If there is only one row left I get the following error in pandas v0.23 which I did not get before (pandas < v0.23). Using geopandas v0.3.0.

My call:
```python
new = gpd.sjoin(rest_points, polygons, how='left', op='intersects')
```

Error message:
```python
ValueError: You are trying to merge on object and int64 columns.
If you wish to proceed you should use pd.concat
```
class: `GeoDataFrame`
method: `merge(self, *args, **kwargs)`
line: `result = DataFrame.merge(self, *args, **kwargs)`

I do not understand the error and why it happens only with the last point (last row) and only with the newest pandas version. I had a look at "What's New" but could not find anything.

Full message:
```python
  File "virtualenv/lib/python3.5/site-packages/geopandas/tools/sjoin.py", line 140,
    in sjoin suffixes=('_%s' % lsuffix, '_%s' % rsuffix))
  File "virtualenv/lib/python3.5/site-packages/geopandas/geodataframe.py", line 418,
     in merge result = DataFrame.merge(self, *args, **kwargs)
  File "virtualenv/lib/python3.5/site-packages/pandas/core/frame.py", line 6379,
     in merge copy=copy, indicator=indicator, validate=validate)
  File "virtualenv/lib/python3.5/site-packages/pandas/core/reshape/merge.py", line 60,
     in mergevalidate=validate)
  File "virtualenv/lib/python3.5/site-packages/pandas/core/reshape/merge.py", line 554,
     in __init__self._maybe_coerce_merge_keys()
  File "virtualenv/lib/python3.5/site-packages/pandas/core/reshape/merge.py", line 980,
        in _maybe_coerce_merge_keys
    raise ValueError(msg)
ValueError: You are trying to merge on object and int64 columns.
If you wish to proceed you should use pd.concat
```

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `geopandas/tools/sjoin.py`
Content:
```
1 from warnings import warn
2 
3 import numpy as np
4 import pandas as pd
5 from shapely import prepared
6 
7 
8 def sjoin(left_df, right_df, how='inner', op='intersects',
9           lsuffix='left', rsuffix='right'):
10     """Spatial join of two GeoDataFrames.
11 
12     Parameters
13     ----------
14     left_df, right_df : GeoDataFrames
15     how : string, default 'inner'
16         The type of join:
17 
18         * 'left': use keys from left_df; retain only left_df geometry column
19         * 'right': use keys from right_df; retain only right_df geometry column
20         * 'inner': use intersection of keys from both dfs; retain only
21           left_df geometry column
22     op : string, default 'intersection'
23         Binary predicate, one of {'intersects', 'contains', 'within'}.
24         See http://toblerity.org/shapely/manual.html#binary-predicates.
25     lsuffix : string, default 'left'
26         Suffix to apply to overlapping column names (left GeoDataFrame).
27     rsuffix : string, default 'right'
28         Suffix to apply to overlapping column names (right GeoDataFrame).
29 
30     """
31     import rtree
32 
33     allowed_hows = ['left', 'right', 'inner']
34     if how not in allowed_hows:
35         raise ValueError("`how` was \"%s\" but is expected to be in %s" %
36                          (how, allowed_hows))
37 
38     allowed_ops = ['contains', 'within', 'intersects']
39     if op not in allowed_ops:
40         raise ValueError("`op` was \"%s\" but is expected to be in %s" %
41                          (op, allowed_ops))
42 
43     if left_df.crs != right_df.crs:
44         warn('CRS of frames being joined does not match!')
45 
46     index_left = 'index_%s' % lsuffix
47     index_right = 'index_%s' % rsuffix
48 
49     # due to GH 352
50     if (any(left_df.columns.isin([index_left, index_right]))
51             or any(right_df.columns.isin([index_left, index_right]))):
52         raise ValueError("'{0}' and '{1}' cannot be names in the frames being"
53                          " joined".format(index_left, index_right))
54 
55     # the rtree spatial index only allows limited (numeric) index types, but an
56     # index in geopandas may be any arbitrary dtype. so reset both indices now
57     # and store references to the original indices, to be reaffixed later.
58     # GH 352
59     left_df = left_df.copy(deep=True)
60     left_df.index = left_df.index.rename(index_left)
61     left_df = left_df.reset_index()
62     right_df = right_df.copy(deep=True)
63     right_df.index = right_df.index.rename(index_right)
64     right_df = right_df.reset_index()
65 
66     if op == "within":
67         # within implemented as the inverse of contains; swap names
68         left_df, right_df = right_df, left_df
69 
70     # insert the bounds in the rtree spatial index
71     right_df_bounds = right_df.geometry.apply(lambda x: x.bounds)
72     stream = ((i, b, None) for i, b in enumerate(right_df_bounds))
73     tree_idx = rtree.index.Index(stream)
74 
75     idxmatch = (left_df.geometry.apply(lambda x: x.bounds)
76                 .apply(lambda x: list(tree_idx.intersection(x))))
77     idxmatch = idxmatch[idxmatch.apply(len) > 0]
78 
79     if idxmatch.shape[0] > 0:
80         # if output from join has overlapping geometries
81         r_idx = np.concatenate(idxmatch.values)
82         l_idx = np.concatenate([[i] * len(v) for i, v in idxmatch.iteritems()])
83 
84         # Vectorize predicate operations
85         def find_intersects(a1, a2):
86             return a1.intersects(a2)
87 
88         def find_contains(a1, a2):
89             return a1.contains(a2)
90 
91         predicate_d = {'intersects': find_intersects,
92                        'contains': find_contains,
93                        'within': find_contains}
94 
95         check_predicates = np.vectorize(predicate_d[op])
96 
97         result = (
98                   pd.DataFrame(
99                       np.column_stack(
100                           [l_idx,
101                            r_idx,
102                            check_predicates(
103                                left_df.geometry
104                                .apply(lambda x: prepared.prep(x))[l_idx],
105                                right_df[right_df.geometry.name][r_idx])
106                            ]))
107                    )
108 
109         result.columns = ['_key_left', '_key_right', 'match_bool']
110         result = (
111                   pd.DataFrame(result[result['match_bool']==1])
112                   .drop('match_bool', axis=1)
113                   )
114 
115     else:
116         # when output from the join has no overlapping geometries
117         result = pd.DataFrame(columns=['_key_left', '_key_right'])
118 
119     if op == "within":
120         # within implemented as the inverse of contains; swap names
121         left_df, right_df = right_df, left_df
122         result = result.rename(columns={'_key_left': '_key_right',
123                                         '_key_right': '_key_left'})
124 
125 
126     if how == 'inner':
127         result = result.set_index('_key_left')
128         joined = (
129                   left_df
130                   .merge(result, left_index=True, right_index=True)
131                   .merge(right_df.drop(right_df.geometry.name, axis=1),
132                       left_on='_key_right', right_index=True,
133                       suffixes=('_%s' % lsuffix, '_%s' % rsuffix))
134                  )
135         joined = joined.set_index(index_left).drop(['_key_right'], axis=1)
136         joined.index.name = None
137     elif how == 'left':
138         result = result.set_index('_key_left')
139         joined = (
140                   left_df
141                   .merge(result, left_index=True, right_index=True, how='left')
142                   .merge(right_df.drop(right_df.geometry.name, axis=1),
143                       how='left', left_on='_key_right', right_index=True,
144                       suffixes=('_%s' % lsuffix, '_%s' % rsuffix))
145                  )
146         joined = joined.set_index(index_left).drop(['_key_right'], axis=1)
147         joined.index.name = None
148     else:  # how == 'right':
149         joined = (
150                   left_df
151                   .drop(left_df.geometry.name, axis=1)
152                   .merge(result.merge(right_df,
153                       left_on='_key_right', right_index=True,
154                       how='right'), left_index=True,
155                       right_on='_key_left', how='right')
156                   .set_index(index_right)
157                  )
158         joined = joined.drop(['_key_left', '_key_right'], axis=1)
159 
160     return joined
161
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/geopandas/tools/sjoin.py b/geopandas/tools/sjoin.py
--- a/geopandas/tools/sjoin.py
+++ b/geopandas/tools/sjoin.py
@@ -114,7 +114,7 @@
 
     else:
         # when output from the join has no overlapping geometries
-        result = pd.DataFrame(columns=['_key_left', '_key_right'])
+        result = pd.DataFrame(columns=['_key_left', '_key_right'], dtype=float)
 
     if op == "within":
         # within implemented as the inverse of contains; swap names

{"golden_diff": "diff --git a/geopandas/tools/sjoin.py b/geopandas/tools/sjoin.py\n--- a/geopandas/tools/sjoin.py\n+++ b/geopandas/tools/sjoin.py\n@@ -114,7 +114,7 @@\n \n     else:\n         # when output from the join has no overlapping geometries\n-        result = pd.DataFrame(columns=['_key_left', '_key_right'])\n+        result = pd.DataFrame(columns=['_key_left', '_key_right'], dtype=float)\n \n     if op == \"within\":\n         # within implemented as the inverse of contains; swap names\n", "issue": "Value error using sjoin with pandas v0.23\nI use the `sjoin` function to add the region name (polygons) to every point within the region. Some points are not in any region, therefore I filter these points and buffer them step by step. So the points layer without intersection becomes smaller and smaller. If there is only one row left I get the following error in pandas v0.23 which I did not get before (pandas < v0.23). Using geopandas v0.3.0.\r\n\r\nMy call:\r\n```python\r\nnew = gpd.sjoin(rest_points, polygons, how='left', op='intersects')\r\n```\r\n\r\nError message:\r\n```python\r\nValueError: You are trying to merge on object and int64 columns.\r\nIf you wish to proceed you should use pd.concat\r\n```\r\nclass: `GeoDataFrame`\r\nmethod: `merge(self, *args, **kwargs)`\r\nline: `result = DataFrame.merge(self, *args, **kwargs)`\r\n\r\nI do not understand the error and why it happens only with the last point (last row) and only with the newest pandas version. I had a look at \"What's New\" but could not find anything.\r\n\r\nFull message:\r\n```python\r\n  File \"virtualenv/lib/python3.5/site-packages/geopandas/tools/sjoin.py\", line 140,\r\n    in sjoin suffixes=('_%s' % lsuffix, '_%s' % rsuffix))\r\n  File \"virtualenv/lib/python3.5/site-packages/geopandas/geodataframe.py\", line 418,\r\n     in merge result = DataFrame.merge(self, *args, **kwargs)\r\n  File \"virtualenv/lib/python3.5/site-packages/pandas/core/frame.py\", line 6379,\r\n     in merge copy=copy, indicator=indicator, validate=validate)\r\n  File \"virtualenv/lib/python3.5/site-packages/pandas/core/reshape/merge.py\", line 60,\r\n     in mergevalidate=validate)\r\n  File \"virtualenv/lib/python3.5/site-packages/pandas/core/reshape/merge.py\", line 554,\r\n     in __init__self._maybe_coerce_merge_keys()\r\n  File \"virtualenv/lib/python3.5/site-packages/pandas/core/reshape/merge.py\", line 980,\r\n        in _maybe_coerce_merge_keys\r\n    raise ValueError(msg)\r\nValueError: You are trying to merge on object and int64 columns.\r\nIf you wish to proceed you should use pd.concat\r\n```\n", "before_files": [{"content": "from warnings import warn\n\nimport numpy as np\nimport pandas as pd\nfrom shapely import prepared\n\n\ndef sjoin(left_df, right_df, how='inner', op='intersects',\n          lsuffix='left', rsuffix='right'):\n    \"\"\"Spatial join of two GeoDataFrames.\n\n    Parameters\n    ----------\n    left_df, right_df : GeoDataFrames\n    how : string, default 'inner'\n        The type of join:\n\n        * 'left': use keys from left_df; retain only left_df geometry column\n        * 'right': use keys from right_df; retain only right_df geometry column\n        * 'inner': use intersection of keys from both dfs; retain only\n          left_df geometry column\n    op : string, default 'intersection'\n        Binary predicate, one of {'intersects', 'contains', 'within'}.\n        See http://toblerity.org/shapely/manual.html#binary-predicates.\n    lsuffix : string, default 'left'\n        Suffix to apply to overlapping column names (left GeoDataFrame).\n    rsuffix : string, default 'right'\n        Suffix to apply to overlapping column names (right GeoDataFrame).\n\n    \"\"\"\n    import rtree\n\n    allowed_hows = ['left', 'right', 'inner']\n    if how not in allowed_hows:\n        raise ValueError(\"`how` was \\\"%s\\\" but is expected to be in %s\" %\n                         (how, allowed_hows))\n\n    allowed_ops = ['contains', 'within', 'intersects']\n    if op not in allowed_ops:\n        raise ValueError(\"`op` was \\\"%s\\\" but is expected to be in %s\" %\n                         (op, allowed_ops))\n\n    if left_df.crs != right_df.crs:\n        warn('CRS of frames being joined does not match!')\n\n    index_left = 'index_%s' % lsuffix\n    index_right = 'index_%s' % rsuffix\n\n    # due to GH 352\n    if (any(left_df.columns.isin([index_left, index_right]))\n            or any(right_df.columns.isin([index_left, index_right]))):\n        raise ValueError(\"'{0}' and '{1}' cannot be names in the frames being\"\n                         \" joined\".format(index_left, index_right))\n\n    # the rtree spatial index only allows limited (numeric) index types, but an\n    # index in geopandas may be any arbitrary dtype. so reset both indices now\n    # and store references to the original indices, to be reaffixed later.\n    # GH 352\n    left_df = left_df.copy(deep=True)\n    left_df.index = left_df.index.rename(index_left)\n    left_df = left_df.reset_index()\n    right_df = right_df.copy(deep=True)\n    right_df.index = right_df.index.rename(index_right)\n    right_df = right_df.reset_index()\n\n    if op == \"within\":\n        # within implemented as the inverse of contains; swap names\n        left_df, right_df = right_df, left_df\n\n    # insert the bounds in the rtree spatial index\n    right_df_bounds = right_df.geometry.apply(lambda x: x.bounds)\n    stream = ((i, b, None) for i, b in enumerate(right_df_bounds))\n    tree_idx = rtree.index.Index(stream)\n\n    idxmatch = (left_df.geometry.apply(lambda x: x.bounds)\n                .apply(lambda x: list(tree_idx.intersection(x))))\n    idxmatch = idxmatch[idxmatch.apply(len) > 0]\n\n    if idxmatch.shape[0] > 0:\n        # if output from join has overlapping geometries\n        r_idx = np.concatenate(idxmatch.values)\n        l_idx = np.concatenate([[i] * len(v) for i, v in idxmatch.iteritems()])\n\n        # Vectorize predicate operations\n        def find_intersects(a1, a2):\n            return a1.intersects(a2)\n\n        def find_contains(a1, a2):\n            return a1.contains(a2)\n\n        predicate_d = {'intersects': find_intersects,\n                       'contains': find_contains,\n                       'within': find_contains}\n\n        check_predicates = np.vectorize(predicate_d[op])\n\n        result = (\n                  pd.DataFrame(\n                      np.column_stack(\n                          [l_idx,\n                           r_idx,\n                           check_predicates(\n                               left_df.geometry\n                               .apply(lambda x: prepared.prep(x))[l_idx],\n                               right_df[right_df.geometry.name][r_idx])\n                           ]))\n                   )\n\n        result.columns = ['_key_left', '_key_right', 'match_bool']\n        result = (\n                  pd.DataFrame(result[result['match_bool']==1])\n                  .drop('match_bool', axis=1)\n                  )\n\n    else:\n        # when output from the join has no overlapping geometries\n        result = pd.DataFrame(columns=['_key_left', '_key_right'])\n\n    if op == \"within\":\n        # within implemented as the inverse of contains; swap names\n        left_df, right_df = right_df, left_df\n        result = result.rename(columns={'_key_left': '_key_right',\n                                        '_key_right': '_key_left'})\n\n\n    if how == 'inner':\n        result = result.set_index('_key_left')\n        joined = (\n                  left_df\n                  .merge(result, left_index=True, right_index=True)\n                  .merge(right_df.drop(right_df.geometry.name, axis=1),\n                      left_on='_key_right', right_index=True,\n                      suffixes=('_%s' % lsuffix, '_%s' % rsuffix))\n                 )\n        joined = joined.set_index(index_left).drop(['_key_right'], axis=1)\n        joined.index.name = None\n    elif how == 'left':\n        result = result.set_index('_key_left')\n        joined = (\n                  left_df\n                  .merge(result, left_index=True, right_index=True, how='left')\n                  .merge(right_df.drop(right_df.geometry.name, axis=1),\n                      how='left', left_on='_key_right', right_index=True,\n                      suffixes=('_%s' % lsuffix, '_%s' % rsuffix))\n                 )\n        joined = joined.set_index(index_left).drop(['_key_right'], axis=1)\n        joined.index.name = None\n    else:  # how == 'right':\n        joined = (\n                  left_df\n                  .drop(left_df.geometry.name, axis=1)\n                  .merge(result.merge(right_df,\n                      left_on='_key_right', right_index=True,\n                      how='right'), left_index=True,\n                      right_on='_key_left', how='right')\n                  .set_index(index_right)\n                 )\n        joined = joined.drop(['_key_left', '_key_right'], axis=1)\n\n    return joined\n", "path": "geopandas/tools/sjoin.py"}], "after_files": [{"content": "from warnings import warn\n\nimport numpy as np\nimport pandas as pd\nfrom shapely import prepared\n\n\ndef sjoin(left_df, right_df, how='inner', op='intersects',\n          lsuffix='left', rsuffix='right'):\n    \"\"\"Spatial join of two GeoDataFrames.\n\n    Parameters\n    ----------\n    left_df, right_df : GeoDataFrames\n    how : string, default 'inner'\n        The type of join:\n\n        * 'left': use keys from left_df; retain only left_df geometry column\n        * 'right': use keys from right_df; retain only right_df geometry column\n        * 'inner': use intersection of keys from both dfs; retain only\n          left_df geometry column\n    op : string, default 'intersection'\n        Binary predicate, one of {'intersects', 'contains', 'within'}.\n        See http://toblerity.org/shapely/manual.html#binary-predicates.\n    lsuffix : string, default 'left'\n        Suffix to apply to overlapping column names (left GeoDataFrame).\n    rsuffix : string, default 'right'\n        Suffix to apply to overlapping column names (right GeoDataFrame).\n\n    \"\"\"\n    import rtree\n\n    allowed_hows = ['left', 'right', 'inner']\n    if how not in allowed_hows:\n        raise ValueError(\"`how` was \\\"%s\\\" but is expected to be in %s\" %\n                         (how, allowed_hows))\n\n    allowed_ops = ['contains', 'within', 'intersects']\n    if op not in allowed_ops:\n        raise ValueError(\"`op` was \\\"%s\\\" but is expected to be in %s\" %\n                         (op, allowed_ops))\n\n    if left_df.crs != right_df.crs:\n        warn('CRS of frames being joined does not match!')\n\n    index_left = 'index_%s' % lsuffix\n    index_right = 'index_%s' % rsuffix\n\n    # due to GH 352\n    if (any(left_df.columns.isin([index_left, index_right]))\n            or any(right_df.columns.isin([index_left, index_right]))):\n        raise ValueError(\"'{0}' and '{1}' cannot be names in the frames being\"\n                         \" joined\".format(index_left, index_right))\n\n    # the rtree spatial index only allows limited (numeric) index types, but an\n    # index in geopandas may be any arbitrary dtype. so reset both indices now\n    # and store references to the original indices, to be reaffixed later.\n    # GH 352\n    left_df = left_df.copy(deep=True)\n    left_df.index = left_df.index.rename(index_left)\n    left_df = left_df.reset_index()\n    right_df = right_df.copy(deep=True)\n    right_df.index = right_df.index.rename(index_right)\n    right_df = right_df.reset_index()\n\n    if op == \"within\":\n        # within implemented as the inverse of contains; swap names\n        left_df, right_df = right_df, left_df\n\n    # insert the bounds in the rtree spatial index\n    right_df_bounds = right_df.geometry.apply(lambda x: x.bounds)\n    stream = ((i, b, None) for i, b in enumerate(right_df_bounds))\n    tree_idx = rtree.index.Index(stream)\n\n    idxmatch = (left_df.geometry.apply(lambda x: x.bounds)\n                .apply(lambda x: list(tree_idx.intersection(x))))\n    idxmatch = idxmatch[idxmatch.apply(len) > 0]\n\n    if idxmatch.shape[0] > 0:\n        # if output from join has overlapping geometries\n        r_idx = np.concatenate(idxmatch.values)\n        l_idx = np.concatenate([[i] * len(v) for i, v in idxmatch.iteritems()])\n\n        # Vectorize predicate operations\n        def find_intersects(a1, a2):\n            return a1.intersects(a2)\n\n        def find_contains(a1, a2):\n            return a1.contains(a2)\n\n        predicate_d = {'intersects': find_intersects,\n                       'contains': find_contains,\n                       'within': find_contains}\n\n        check_predicates = np.vectorize(predicate_d[op])\n\n        result = (\n                  pd.DataFrame(\n                      np.column_stack(\n                          [l_idx,\n                           r_idx,\n                           check_predicates(\n                               left_df.geometry\n                               .apply(lambda x: prepared.prep(x))[l_idx],\n                               right_df[right_df.geometry.name][r_idx])\n                           ]))\n                   )\n\n        result.columns = ['_key_left', '_key_right', 'match_bool']\n        result = (\n                  pd.DataFrame(result[result['match_bool']==1])\n                  .drop('match_bool', axis=1)\n                  )\n\n    else:\n        # when output from the join has no overlapping geometries\n        result = pd.DataFrame(columns=['_key_left', '_key_right'], dtype=float)\n\n    if op == \"within\":\n        # within implemented as the inverse of contains; swap names\n        left_df, right_df = right_df, left_df\n        result = result.rename(columns={'_key_left': '_key_right',\n                                        '_key_right': '_key_left'})\n\n\n    if how == 'inner':\n        result = result.set_index('_key_left')\n        joined = (\n                  left_df\n                  .merge(result, left_index=True, right_index=True)\n                  .merge(right_df.drop(right_df.geometry.name, axis=1),\n                      left_on='_key_right', right_index=True,\n                      suffixes=('_%s' % lsuffix, '_%s' % rsuffix))\n                 )\n        joined = joined.set_index(index_left).drop(['_key_right'], axis=1)\n        joined.index.name = None\n    elif how == 'left':\n        result = result.set_index('_key_left')\n        joined = (\n                  left_df\n                  .merge(result, left_index=True, right_index=True, how='left')\n                  .merge(right_df.drop(right_df.geometry.name, axis=1),\n                      how='left', left_on='_key_right', right_index=True,\n                      suffixes=('_%s' % lsuffix, '_%s' % rsuffix))\n                 )\n        joined = joined.set_index(index_left).drop(['_key_right'], axis=1)\n        joined.index.name = None\n    else:  # how == 'right':\n        joined = (\n                  left_df\n                  .drop(left_df.geometry.name, axis=1)\n                  .merge(result.merge(right_df,\n                      left_on='_key_right', right_index=True,\n                      how='right'), left_index=True,\n                      right_on='_key_left', how='right')\n                  .set_index(index_right)\n                 )\n        joined = joined.drop(['_key_left', '_key_right'], axis=1)\n\n    return joined\n", "path": "geopandas/tools/sjoin.py"}]}