We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
expose Mapzen Search geocoding service
GeoPy includes [support](https://github.com/geopy/geopy/pull/183) for geocoding using [Mapzen Search](https://mapzen.com/documentation/search/).

Would be useful to expose this as a provider through `geopandas.geocode`.
ENH: expose all geopy geocoding services
The current behavior of the geocoding (and reverse) functionality in GeoPandas takes a service provider as a string, which is then mapped to a `geopy.geocoders` instance with a hard coded dict. Instead of taking a string (and, for at least some deprecation time period, in addition), we could take a `geopy.geocoders` class as an argument. In addition to providing access to lots of services (in addition to Mapzen, explicitly requested in #468), when `geopy` adds or removes services, we wouldn't need to worry about keeping up. The different services already accept different args/kwargs, and thus the user must already have familiarity with the different services if, e.g., using an API key for the service. I'd suggest still leaving GoogleV3 as the default, so the experience for most users wouldn't change at all. In general, the call would change from

    df = gpd.tools.geocoding.reverse_geocode([Point(-71.0594869, 42.3584697), Point(-77.0365305, 38.8977332)], 
                                              provider='nominatim')

to 

    df = gpd.tools.geocoding.reverse_geocode([Point(-71.0594869, 42.3584697), Point(-77.0365305, 38.8977332)], 
                                              provider=geopy.geocoders.Nominatim)

Anything I'm missing here? If not, happy to implement this change. 


--- 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/geocoding.py`
Content:
```
1 from collections import defaultdict
2 import time
3 
4 from fiona.crs import from_epsg
5 import numpy as np
6 import pandas as pd
7 from shapely.geometry import Point
8 from six import iteritems
9 
10 import geopandas as gpd
11 
12 
13 def _throttle_time(provider):
14     """ Amount of time to wait between requests to a geocoding API.
15 
16     Currently implemented for Nominatim, as their terms of service
17     require a maximum of 1 request per second.
18     https://wiki.openstreetmap.org/wiki/Nominatim_usage_policy
19     """
20     if provider == 'nominatim':
21         return 1
22     else:
23         return 0
24 
25 
26 def geocode(strings, provider='googlev3', **kwargs):
27     """
28     Geocode a set of strings and get a GeoDataFrame of the resulting points.
29 
30     Parameters
31     ----------
32     strings : list or Series of addresses to geocode
33     provider : geopy geocoder to use, default 'googlev3'
34         Some providers require additional arguments such as access keys
35         See each geocoder's specific parameters in geopy.geocoders
36         * googlev3, default
37         * bing
38         * google
39         * yahoo
40         * mapquest
41         * openmapquest
42 
43     Ensure proper use of the results by consulting the Terms of Service for
44     your provider.
45 
46     Geocoding requires geopy. Install it using 'pip install geopy'. See also
47     https://github.com/geopy/geopy
48 
49     Example
50     -------
51     >>> df = geocode(['boston, ma', '1600 pennsylvania ave. washington, dc'])
52 
53                                                  address  \
54     0                                    Boston, MA, USA
55     1  1600 Pennsylvania Avenue Northwest, President'...
56 
57                              geometry
58     0  POINT (-71.0597732 42.3584308)
59     1  POINT (-77.0365305 38.8977332)
60 
61     """
62     return _query(strings, True, provider, **kwargs)
63 
64 
65 def reverse_geocode(points, provider='googlev3', **kwargs):
66     """
67     Reverse geocode a set of points and get a GeoDataFrame of the resulting
68     addresses.
69 
70     The points
71 
72     Parameters
73     ----------
74     points : list or Series of Shapely Point objects.
75         x coordinate is longitude
76         y coordinate is latitude
77     provider : geopy geocoder to use, default 'googlev3'
78         These are the same options as the geocode() function
79         Some providers require additional arguments such as access keys
80         See each geocoder's specific parameters in geopy.geocoders
81         * googlev3, default
82         * bing
83         * google
84         * yahoo
85         * mapquest
86         * openmapquest
87 
88     Ensure proper use of the results by consulting the Terms of Service for
89     your provider.
90 
91     Reverse geocoding requires geopy. Install it using 'pip install geopy'.
92     See also https://github.com/geopy/geopy
93 
94     Example
95     -------
96     >>> df = reverse_geocode([Point(-71.0594869, 42.3584697),
97                               Point(-77.0365305, 38.8977332)])
98 
99                                              address  \
100     0             29 Court Square, Boston, MA 02108, USA
101     1  1600 Pennsylvania Avenue Northwest, President'...
102 
103                              geometry
104     0  POINT (-71.0594869 42.3584697)
105     1  POINT (-77.0365305 38.8977332)
106 
107     """
108     return _query(points, False, provider, **kwargs)
109 
110 
111 def _query(data, forward, provider, **kwargs):
112     import geopy
113     from geopy.geocoders.base import GeocoderQueryError
114 
115     if not isinstance(data, pd.Series):
116         data = pd.Series(data)
117 
118     # workaround changed name in 0.96
119     try:
120         Yahoo = geopy.geocoders.YahooPlaceFinder
121     except AttributeError:
122         Yahoo = geopy.geocoders.Yahoo
123 
124     coders = {'googlev3': geopy.geocoders.GoogleV3,
125               'bing': geopy.geocoders.Bing,
126               'yahoo': Yahoo,
127               'openmapquest': geopy.geocoders.OpenMapQuest,
128               'nominatim': geopy.geocoders.Nominatim}
129 
130     if provider not in coders:
131         raise ValueError('Unknown geocoding provider: {0}'.format(provider))
132 
133     coder = coders[provider](**kwargs)
134     results = {}
135     for i, s in iteritems(data):
136         try:
137             if forward:
138                 results[i] = coder.geocode(s)
139             else:
140                 results[i] = coder.reverse((s.y, s.x), exactly_one=True)
141         except (GeocoderQueryError, ValueError):
142             results[i] = (None, None)
143         time.sleep(_throttle_time(provider))
144 
145     df = _prepare_geocode_result(results)
146     return df
147 
148 
149 def _prepare_geocode_result(results):
150     """
151     Helper function for the geocode function
152 
153     Takes a dict where keys are index entries, values are tuples containing:
154     (address, (lat, lon))
155 
156     """
157     # Prepare the data for the DataFrame as a dict of lists
158     d = defaultdict(list)
159     index = []
160 
161     for i, s in iteritems(results):
162         address, loc = s
163 
164         # loc is lat, lon and we want lon, lat
165         if loc is None:
166             p = Point()
167         else:
168             p = Point(loc[1], loc[0])
169 
170         if address is None:
171             address = np.nan
172 
173         d['geometry'].append(p)
174         d['address'].append(address)
175         index.append(i)
176 
177     df = gpd.GeoDataFrame(d, index=index)
178     df.crs = from_epsg(4326)
179 
180     return df
181
```
--- 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/geocoding.py b/geopandas/tools/geocoding.py
--- a/geopandas/tools/geocoding.py
+++ b/geopandas/tools/geocoding.py
@@ -5,7 +5,7 @@
 import numpy as np
 import pandas as pd
 from shapely.geometry import Point
-from six import iteritems
+from six import iteritems, string_types
 
 import geopandas as gpd
 
@@ -17,7 +17,8 @@
     require a maximum of 1 request per second.
     https://wiki.openstreetmap.org/wiki/Nominatim_usage_policy
     """
-    if provider == 'nominatim':
+    import geopy.geocoders
+    if provider == geopy.geocoders.Nominatim:
         return 1
     else:
         return 0
@@ -30,15 +31,14 @@
     Parameters
     ----------
     strings : list or Series of addresses to geocode
-    provider : geopy geocoder to use, default 'googlev3'
+    provider : str or geopy.geocoder
+        Specifies geocoding service to use, default is 'googlev3'.
+        Either the string name used by geopy (as specified in
+        geopy.geocoders.SERVICE_TO_GEOCODER) or a geopy Geocoder instance
+        (e.g., geopy.geocoders.GoogleV3) may be used.
+
         Some providers require additional arguments such as access keys
         See each geocoder's specific parameters in geopy.geocoders
-        * googlev3, default
-        * bing
-        * google
-        * yahoo
-        * mapquest
-        * openmapquest
 
     Ensure proper use of the results by consulting the Terms of Service for
     your provider.
@@ -74,16 +74,14 @@
     points : list or Series of Shapely Point objects.
         x coordinate is longitude
         y coordinate is latitude
-    provider : geopy geocoder to use, default 'googlev3'
-        These are the same options as the geocode() function
+    provider : str or geopy.geocoder (opt)
+        Specifies geocoding service to use, default is 'googlev3'.
+        Either the string name used by geopy (as specified in
+        geopy.geocoders.SERVICE_TO_GEOCODER) or a geopy Geocoder instance
+        (e.g., geopy.geocoders.GoogleV3) may be used.
+
         Some providers require additional arguments such as access keys
         See each geocoder's specific parameters in geopy.geocoders
-        * googlev3, default
-        * bing
-        * google
-        * yahoo
-        * mapquest
-        * openmapquest
 
     Ensure proper use of the results by consulting the Terms of Service for
     your provider.
@@ -109,28 +107,18 @@
 
 
 def _query(data, forward, provider, **kwargs):
+    # generic wrapper for calls over lists to geopy Geocoders
     import geopy
     from geopy.geocoders.base import GeocoderQueryError
+    from geopy.geocoders import get_geocoder_for_service
 
     if not isinstance(data, pd.Series):
         data = pd.Series(data)
 
-    # workaround changed name in 0.96
-    try:
-        Yahoo = geopy.geocoders.YahooPlaceFinder
-    except AttributeError:
-        Yahoo = geopy.geocoders.Yahoo
-
-    coders = {'googlev3': geopy.geocoders.GoogleV3,
-              'bing': geopy.geocoders.Bing,
-              'yahoo': Yahoo,
-              'openmapquest': geopy.geocoders.OpenMapQuest,
-              'nominatim': geopy.geocoders.Nominatim}
-
-    if provider not in coders:
-        raise ValueError('Unknown geocoding provider: {0}'.format(provider))
+    if isinstance(provider, string_types):
+        provider = get_geocoder_for_service(provider)
 
-    coder = coders[provider](**kwargs)
+    coder = provider(**kwargs)
     results = {}
     for i, s in iteritems(data):
         try:

{"golden_diff": "diff --git a/geopandas/tools/geocoding.py b/geopandas/tools/geocoding.py\n--- a/geopandas/tools/geocoding.py\n+++ b/geopandas/tools/geocoding.py\n@@ -5,7 +5,7 @@\n import numpy as np\n import pandas as pd\n from shapely.geometry import Point\n-from six import iteritems\n+from six import iteritems, string_types\n \n import geopandas as gpd\n \n@@ -17,7 +17,8 @@\n     require a maximum of 1 request per second.\n     https://wiki.openstreetmap.org/wiki/Nominatim_usage_policy\n     \"\"\"\n-    if provider == 'nominatim':\n+    import geopy.geocoders\n+    if provider == geopy.geocoders.Nominatim:\n         return 1\n     else:\n         return 0\n@@ -30,15 +31,14 @@\n     Parameters\n     ----------\n     strings : list or Series of addresses to geocode\n-    provider : geopy geocoder to use, default 'googlev3'\n+    provider : str or geopy.geocoder\n+        Specifies geocoding service to use, default is 'googlev3'.\n+        Either the string name used by geopy (as specified in\n+        geopy.geocoders.SERVICE_TO_GEOCODER) or a geopy Geocoder instance\n+        (e.g., geopy.geocoders.GoogleV3) may be used.\n+\n         Some providers require additional arguments such as access keys\n         See each geocoder's specific parameters in geopy.geocoders\n-        * googlev3, default\n-        * bing\n-        * google\n-        * yahoo\n-        * mapquest\n-        * openmapquest\n \n     Ensure proper use of the results by consulting the Terms of Service for\n     your provider.\n@@ -74,16 +74,14 @@\n     points : list or Series of Shapely Point objects.\n         x coordinate is longitude\n         y coordinate is latitude\n-    provider : geopy geocoder to use, default 'googlev3'\n-        These are the same options as the geocode() function\n+    provider : str or geopy.geocoder (opt)\n+        Specifies geocoding service to use, default is 'googlev3'.\n+        Either the string name used by geopy (as specified in\n+        geopy.geocoders.SERVICE_TO_GEOCODER) or a geopy Geocoder instance\n+        (e.g., geopy.geocoders.GoogleV3) may be used.\n+\n         Some providers require additional arguments such as access keys\n         See each geocoder's specific parameters in geopy.geocoders\n-        * googlev3, default\n-        * bing\n-        * google\n-        * yahoo\n-        * mapquest\n-        * openmapquest\n \n     Ensure proper use of the results by consulting the Terms of Service for\n     your provider.\n@@ -109,28 +107,18 @@\n \n \n def _query(data, forward, provider, **kwargs):\n+    # generic wrapper for calls over lists to geopy Geocoders\n     import geopy\n     from geopy.geocoders.base import GeocoderQueryError\n+    from geopy.geocoders import get_geocoder_for_service\n \n     if not isinstance(data, pd.Series):\n         data = pd.Series(data)\n \n-    # workaround changed name in 0.96\n-    try:\n-        Yahoo = geopy.geocoders.YahooPlaceFinder\n-    except AttributeError:\n-        Yahoo = geopy.geocoders.Yahoo\n-\n-    coders = {'googlev3': geopy.geocoders.GoogleV3,\n-              'bing': geopy.geocoders.Bing,\n-              'yahoo': Yahoo,\n-              'openmapquest': geopy.geocoders.OpenMapQuest,\n-              'nominatim': geopy.geocoders.Nominatim}\n-\n-    if provider not in coders:\n-        raise ValueError('Unknown geocoding provider: {0}'.format(provider))\n+    if isinstance(provider, string_types):\n+        provider = get_geocoder_for_service(provider)\n \n-    coder = coders[provider](**kwargs)\n+    coder = provider(**kwargs)\n     results = {}\n     for i, s in iteritems(data):\n         try:\n", "issue": "expose Mapzen Search geocoding service\nGeoPy includes [support](https://github.com/geopy/geopy/pull/183) for geocoding using [Mapzen Search](https://mapzen.com/documentation/search/).\r\n\r\nWould be useful to expose this as a provider through `geopandas.geocode`.\nENH: expose all geopy geocoding services\nThe current behavior of the geocoding (and reverse) functionality in GeoPandas takes a service provider as a string, which is then mapped to a `geopy.geocoders` instance with a hard coded dict. Instead of taking a string (and, for at least some deprecation time period, in addition), we could take a `geopy.geocoders` class as an argument. In addition to providing access to lots of services (in addition to Mapzen, explicitly requested in #468), when `geopy` adds or removes services, we wouldn't need to worry about keeping up. The different services already accept different args/kwargs, and thus the user must already have familiarity with the different services if, e.g., using an API key for the service. I'd suggest still leaving GoogleV3 as the default, so the experience for most users wouldn't change at all. In general, the call would change from\r\n\r\n    df = gpd.tools.geocoding.reverse_geocode([Point(-71.0594869, 42.3584697), Point(-77.0365305, 38.8977332)], \r\n                                              provider='nominatim')\r\n\r\nto \r\n\r\n    df = gpd.tools.geocoding.reverse_geocode([Point(-71.0594869, 42.3584697), Point(-77.0365305, 38.8977332)], \r\n                                              provider=geopy.geocoders.Nominatim)\r\n\r\nAnything I'm missing here? If not, happy to implement this change. \r\n\n", "before_files": [{"content": "from collections import defaultdict\nimport time\n\nfrom fiona.crs import from_epsg\nimport numpy as np\nimport pandas as pd\nfrom shapely.geometry import Point\nfrom six import iteritems\n\nimport geopandas as gpd\n\n\ndef _throttle_time(provider):\n    \"\"\" Amount of time to wait between requests to a geocoding API.\n\n    Currently implemented for Nominatim, as their terms of service\n    require a maximum of 1 request per second.\n    https://wiki.openstreetmap.org/wiki/Nominatim_usage_policy\n    \"\"\"\n    if provider == 'nominatim':\n        return 1\n    else:\n        return 0\n\n\ndef geocode(strings, provider='googlev3', **kwargs):\n    \"\"\"\n    Geocode a set of strings and get a GeoDataFrame of the resulting points.\n\n    Parameters\n    ----------\n    strings : list or Series of addresses to geocode\n    provider : geopy geocoder to use, default 'googlev3'\n        Some providers require additional arguments such as access keys\n        See each geocoder's specific parameters in geopy.geocoders\n        * googlev3, default\n        * bing\n        * google\n        * yahoo\n        * mapquest\n        * openmapquest\n\n    Ensure proper use of the results by consulting the Terms of Service for\n    your provider.\n\n    Geocoding requires geopy. Install it using 'pip install geopy'. See also\n    https://github.com/geopy/geopy\n\n    Example\n    -------\n    >>> df = geocode(['boston, ma', '1600 pennsylvania ave. washington, dc'])\n\n                                                 address  \\\n    0                                    Boston, MA, USA\n    1  1600 Pennsylvania Avenue Northwest, President'...\n\n                             geometry\n    0  POINT (-71.0597732 42.3584308)\n    1  POINT (-77.0365305 38.8977332)\n\n    \"\"\"\n    return _query(strings, True, provider, **kwargs)\n\n\ndef reverse_geocode(points, provider='googlev3', **kwargs):\n    \"\"\"\n    Reverse geocode a set of points and get a GeoDataFrame of the resulting\n    addresses.\n\n    The points\n\n    Parameters\n    ----------\n    points : list or Series of Shapely Point objects.\n        x coordinate is longitude\n        y coordinate is latitude\n    provider : geopy geocoder to use, default 'googlev3'\n        These are the same options as the geocode() function\n        Some providers require additional arguments such as access keys\n        See each geocoder's specific parameters in geopy.geocoders\n        * googlev3, default\n        * bing\n        * google\n        * yahoo\n        * mapquest\n        * openmapquest\n\n    Ensure proper use of the results by consulting the Terms of Service for\n    your provider.\n\n    Reverse geocoding requires geopy. Install it using 'pip install geopy'.\n    See also https://github.com/geopy/geopy\n\n    Example\n    -------\n    >>> df = reverse_geocode([Point(-71.0594869, 42.3584697),\n                              Point(-77.0365305, 38.8977332)])\n\n                                             address  \\\n    0             29 Court Square, Boston, MA 02108, USA\n    1  1600 Pennsylvania Avenue Northwest, President'...\n\n                             geometry\n    0  POINT (-71.0594869 42.3584697)\n    1  POINT (-77.0365305 38.8977332)\n\n    \"\"\"\n    return _query(points, False, provider, **kwargs)\n\n\ndef _query(data, forward, provider, **kwargs):\n    import geopy\n    from geopy.geocoders.base import GeocoderQueryError\n\n    if not isinstance(data, pd.Series):\n        data = pd.Series(data)\n\n    # workaround changed name in 0.96\n    try:\n        Yahoo = geopy.geocoders.YahooPlaceFinder\n    except AttributeError:\n        Yahoo = geopy.geocoders.Yahoo\n\n    coders = {'googlev3': geopy.geocoders.GoogleV3,\n              'bing': geopy.geocoders.Bing,\n              'yahoo': Yahoo,\n              'openmapquest': geopy.geocoders.OpenMapQuest,\n              'nominatim': geopy.geocoders.Nominatim}\n\n    if provider not in coders:\n        raise ValueError('Unknown geocoding provider: {0}'.format(provider))\n\n    coder = coders[provider](**kwargs)\n    results = {}\n    for i, s in iteritems(data):\n        try:\n            if forward:\n                results[i] = coder.geocode(s)\n            else:\n                results[i] = coder.reverse((s.y, s.x), exactly_one=True)\n        except (GeocoderQueryError, ValueError):\n            results[i] = (None, None)\n        time.sleep(_throttle_time(provider))\n\n    df = _prepare_geocode_result(results)\n    return df\n\n\ndef _prepare_geocode_result(results):\n    \"\"\"\n    Helper function for the geocode function\n\n    Takes a dict where keys are index entries, values are tuples containing:\n    (address, (lat, lon))\n\n    \"\"\"\n    # Prepare the data for the DataFrame as a dict of lists\n    d = defaultdict(list)\n    index = []\n\n    for i, s in iteritems(results):\n        address, loc = s\n\n        # loc is lat, lon and we want lon, lat\n        if loc is None:\n            p = Point()\n        else:\n            p = Point(loc[1], loc[0])\n\n        if address is None:\n            address = np.nan\n\n        d['geometry'].append(p)\n        d['address'].append(address)\n        index.append(i)\n\n    df = gpd.GeoDataFrame(d, index=index)\n    df.crs = from_epsg(4326)\n\n    return df\n", "path": "geopandas/tools/geocoding.py"}], "after_files": [{"content": "from collections import defaultdict\nimport time\n\nfrom fiona.crs import from_epsg\nimport numpy as np\nimport pandas as pd\nfrom shapely.geometry import Point\nfrom six import iteritems, string_types\n\nimport geopandas as gpd\n\n\ndef _throttle_time(provider):\n    \"\"\" Amount of time to wait between requests to a geocoding API.\n\n    Currently implemented for Nominatim, as their terms of service\n    require a maximum of 1 request per second.\n    https://wiki.openstreetmap.org/wiki/Nominatim_usage_policy\n    \"\"\"\n    import geopy.geocoders\n    if provider == geopy.geocoders.Nominatim:\n        return 1\n    else:\n        return 0\n\n\ndef geocode(strings, provider='googlev3', **kwargs):\n    \"\"\"\n    Geocode a set of strings and get a GeoDataFrame of the resulting points.\n\n    Parameters\n    ----------\n    strings : list or Series of addresses to geocode\n    provider : str or geopy.geocoder\n        Specifies geocoding service to use, default is 'googlev3'.\n        Either the string name used by geopy (as specified in\n        geopy.geocoders.SERVICE_TO_GEOCODER) or a geopy Geocoder instance\n        (e.g., geopy.geocoders.GoogleV3) may be used.\n\n        Some providers require additional arguments such as access keys\n        See each geocoder's specific parameters in geopy.geocoders\n\n    Ensure proper use of the results by consulting the Terms of Service for\n    your provider.\n\n    Geocoding requires geopy. Install it using 'pip install geopy'. See also\n    https://github.com/geopy/geopy\n\n    Example\n    -------\n    >>> df = geocode(['boston, ma', '1600 pennsylvania ave. washington, dc'])\n\n                                                 address  \\\n    0                                    Boston, MA, USA\n    1  1600 Pennsylvania Avenue Northwest, President'...\n\n                             geometry\n    0  POINT (-71.0597732 42.3584308)\n    1  POINT (-77.0365305 38.8977332)\n\n    \"\"\"\n    return _query(strings, True, provider, **kwargs)\n\n\ndef reverse_geocode(points, provider='googlev3', **kwargs):\n    \"\"\"\n    Reverse geocode a set of points and get a GeoDataFrame of the resulting\n    addresses.\n\n    The points\n\n    Parameters\n    ----------\n    points : list or Series of Shapely Point objects.\n        x coordinate is longitude\n        y coordinate is latitude\n    provider : str or geopy.geocoder (opt)\n        Specifies geocoding service to use, default is 'googlev3'.\n        Either the string name used by geopy (as specified in\n        geopy.geocoders.SERVICE_TO_GEOCODER) or a geopy Geocoder instance\n        (e.g., geopy.geocoders.GoogleV3) may be used.\n\n        Some providers require additional arguments such as access keys\n        See each geocoder's specific parameters in geopy.geocoders\n\n    Ensure proper use of the results by consulting the Terms of Service for\n    your provider.\n\n    Reverse geocoding requires geopy. Install it using 'pip install geopy'.\n    See also https://github.com/geopy/geopy\n\n    Example\n    -------\n    >>> df = reverse_geocode([Point(-71.0594869, 42.3584697),\n                              Point(-77.0365305, 38.8977332)])\n\n                                             address  \\\n    0             29 Court Square, Boston, MA 02108, USA\n    1  1600 Pennsylvania Avenue Northwest, President'...\n\n                             geometry\n    0  POINT (-71.0594869 42.3584697)\n    1  POINT (-77.0365305 38.8977332)\n\n    \"\"\"\n    return _query(points, False, provider, **kwargs)\n\n\ndef _query(data, forward, provider, **kwargs):\n    # generic wrapper for calls over lists to geopy Geocoders\n    import geopy\n    from geopy.geocoders.base import GeocoderQueryError\n    from geopy.geocoders import get_geocoder_for_service\n\n    if not isinstance(data, pd.Series):\n        data = pd.Series(data)\n\n    if isinstance(provider, string_types):\n        provider = get_geocoder_for_service(provider)\n\n    coder = provider(**kwargs)\n    results = {}\n    for i, s in iteritems(data):\n        try:\n            if forward:\n                results[i] = coder.geocode(s)\n            else:\n                results[i] = coder.reverse((s.y, s.x), exactly_one=True)\n        except (GeocoderQueryError, ValueError):\n            results[i] = (None, None)\n        time.sleep(_throttle_time(provider))\n\n    df = _prepare_geocode_result(results)\n    return df\n\n\ndef _prepare_geocode_result(results):\n    \"\"\"\n    Helper function for the geocode function\n\n    Takes a dict where keys are index entries, values are tuples containing:\n    (address, (lat, lon))\n\n    \"\"\"\n    # Prepare the data for the DataFrame as a dict of lists\n    d = defaultdict(list)\n    index = []\n\n    for i, s in iteritems(results):\n        address, loc = s\n\n        # loc is lat, lon and we want lon, lat\n        if loc is None:\n            p = Point()\n        else:\n            p = Point(loc[1], loc[0])\n\n        if address is None:\n            address = np.nan\n\n        d['geometry'].append(p)\n        d['address'].append(address)\n        index.append(i)\n\n    df = gpd.GeoDataFrame(d, index=index)\n    df.crs = from_epsg(4326)\n\n    return df\n", "path": "geopandas/tools/geocoding.py"}]}