fixed geo accessor example in extending.rst
State: closed

The previous code was incompatible with the following paragraph. See the second block of code in https://pandas.pydata.org/pandas-docs/stable/development/extending.html#registering-custom-accessors

- [ ] closes #xxxx
- [ ] tests added / passed
- [ ] passes `git diff upstream/master -u -- "*.py" | flake8 --diff`
- [ ] whatsnew entry


<details>



```python
import pandas as pd
import numpy as np
```

# Before

## Register the DataFrame accessor "geo"


```python
@pd.api.extensions.register_dataframe_accessor("geo")
class GeoAccessor(object):
    def __init__(self, pandas_obj):
        self._validate(pandas_obj)
        self._obj = pandas_obj

    @staticmethod
    def _validate(obj):
        if 'lat' not in obj.columns or 'lon' not in obj.columns:
            raise AttributeError("Must have 'lat' and 'lon'.")

    @property
    def center(self):
        # return the geographic center point of this DataFrame
        lat = self._obj.latitude
        lon = self._obj.longitude
        return (float(lon.mean()), float(lat.mean()))

    def plot(self):
        # plot this array's data on a map, e.g., using Cartopy
        pass
```

## Test the DataFrame accessor "geo"


```python
ds = pd.DataFrame({'longitude': np.linspace(0, 10),
                   'latitude': np.linspace(0, 20)})
ds.geo.center
```


    ---------------------------------------------------------------------------

    AttributeError                            Traceback (most recent call last)

    <ipython-input-3-71f0445704bc> in <module>()
          1 ds = pd.DataFrame({'longitude': np.linspace(0, 10),
          2                    'latitude': np.linspace(0, 20)})
    ----> 3 ds.geo.center
    

    ~\Anaconda3\lib\site-packages\pandas\core\generic.py in __getattr__(self, name)
       5061         if (name in self._internal_names_set or name in self._metadata or
       5062                 name in self._accessors):
    -> 5063             return object.__getattribute__(self, name)
       5064         else:
       5065             if self._info_axis._can_hold_identifiers_and_holds_name(name):
    

    ~\Anaconda3\lib\site-packages\pandas\core\accessor.py in __get__(self, obj, cls)
        169             # we're accessing the attribute of the class, i.e., Dataset.geo
        170             return self._accessor
    --> 171         accessor_obj = self._accessor(obj)
        172         # Replace the property with the accessor object. Inspired by:
        173         # http://www.pydanny.com/cached-property.html
    

    <ipython-input-2-114caa965d3b> in __init__(self, pandas_obj)
          2 class GeoAccessor(object):
          3     def __init__(self, pandas_obj):
    ----> 4         self._validate(pandas_obj)
          5         self._obj = pandas_obj
          6 
    

    <ipython-input-2-114caa965d3b> in _validate(obj)
          8     def _validate(obj):
          9         if 'lat' not in obj.columns or 'lon' not in obj.columns:
    ---> 10             raise AttributeError("Must have 'lat' and 'lon'.")
         11 
         12     @property
    

    AttributeError: Must have 'lat' and 'lon'.


# After

## Register the DataFrame accessor "geo"


```python
@pd.api.extensions.register_dataframe_accessor("geo")
class GeoAccessor(object):
    def __init__(self, pandas_obj):
        self._validate(pandas_obj)
        self._obj = pandas_obj

    @staticmethod
    def _validate(obj):
       # verify each column name contains 'lat' or 'lon'
       for col in obj.columns:
            if 'lat' not in col and 'lon' not in col:
                raise AttributeError("Must have 'lat' and 'lon'.")

    @property
    def center(self):
        # return the geographic center point of this DataFrame
        lat = self._obj.latitude
        lon = self._obj.longitude
        return (float(lon.mean()), float(lat.mean()))

    def plot(self):
        # plot this array's data on a map, e.g., using Cartopy
        pass
```
      
    

## Test the DataFrame accessor "geo"


```python
ds = pd.DataFrame({'longitude': np.linspace(0, 10),
                   'latitude': np.linspace(0, 20)})
ds.geo.center
```




    (5.0, 10.0)


</details>


Labels:
name: Docs

Comments:
I don't think there's an issue with the example. The intention was do demonstrate a geo dataframe with `lat` and `lon` columns. What in the text led you to think that each column must contain one of those substrings?

> Nice catch! Weird that we hadn't caught that yet in our builds...

This is a code-block, not an ipython block.
> I don't think there's an issue with the example. The intention was do demonstrate a geo dataframe with `lat` and `lon` columns. What in the text led you to think that each column must contain one of those substrings?
> 
> > Nice catch! Weird that we hadn't caught that yet in our builds...
> 
> This is a code-block, not an ipython block.

The code would not work previously (see Details at the end of my post) you are right though I misinterpreted the intent and I would like to change my commit to:

```
       @staticmethod
       def _validate(obj):
           # verify there is a column latitude and a column longitude
           if 'latitude' not in obj.columns or 'longitude' not in obj.columns:
               raise AttributeError("Must have 'latitude' and 'longitude'.")
```
Do I push a new commit into my branch? I don't know how to modify an existing commit.

Thank you
> I don't think there's an issue with the example. The intention was do demonstrate a geo dataframe with `lat` and `lon` columns.

@TomAugspurger : If that's the case, then the code should be consistent anyhow.

> Do I push a new commit into my branch? I don't know how to modify an existing commit.

@ThibTrip : You can modify an existing commit, but pushing a new commit is easier.
# [Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/25420?src=pr&el=h1) Report
> Merging [#25420](https://codecov.io/gh/pandas-dev/pandas/pull/25420?src=pr&el=desc) into [master](https://codecov.io/gh/pandas-dev/pandas/commit/15d8178a3f81febe4d8ddb033d07e57359eb6167?src=pr&el=desc) will **not change** coverage.
> The diff coverage is `n/a`.

[![Impacted file tree graph](https://codecov.io/gh/pandas-dev/pandas/pull/25420/graphs/tree.svg?width=650&token=eZ4WkYLtcO&height=150&src=pr)](https://codecov.io/gh/pandas-dev/pandas/pull/25420?src=pr&el=tree)

```diff
@@           Coverage Diff           @@
##           master   #25420   +/-   ##
=======================================
  Coverage   91.73%   91.73%           
=======================================
  Files         173      173           
  Lines       52848    52848           
=======================================
  Hits        48482    48482           
  Misses       4366     4366
```

| Flag | Coverage Δ | |
|---|---|---|
| #multiple | `90.3% <ø> (ø)` | :arrow_up: |
| #single | `41.7% <ø> (ø)` | :arrow_up: |

| [Impacted Files](https://codecov.io/gh/pandas-dev/pandas/pull/25420?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [pandas/errors/\_\_init\_\_.py](https://codecov.io/gh/pandas-dev/pandas/pull/25420/diff?src=pr&el=tree#diff-cGFuZGFzL2Vycm9ycy9fX2luaXRfXy5weQ==) | `100% <0%> (ø)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/25420?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/25420?src=pr&el=footer). Last update [15d8178...120c84c](https://codecov.io/gh/pandas-dev/pandas/pull/25420?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

# [Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/25420?src=pr&el=h1) Report
> Merging [#25420](https://codecov.io/gh/pandas-dev/pandas/pull/25420?src=pr&el=desc) into [master](https://codecov.io/gh/pandas-dev/pandas/commit/15d8178a3f81febe4d8ddb033d07e57359eb6167?src=pr&el=desc) will **increase** coverage by `<.01%`.
> The diff coverage is `n/a`.

[![Impacted file tree graph](https://codecov.io/gh/pandas-dev/pandas/pull/25420/graphs/tree.svg?width=650&token=eZ4WkYLtcO&height=150&src=pr)](https://codecov.io/gh/pandas-dev/pandas/pull/25420?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master   #25420      +/-   ##
==========================================
+ Coverage   91.73%   91.74%   +<.01%     
==========================================
  Files         173      173              
  Lines       52848    52848              
==========================================
+ Hits        48482    48483       +1     
+ Misses       4366     4365       -1
```

| Flag | Coverage Δ | |
|---|---|---|
| #multiple | `90.3% <ø> (ø)` | :arrow_up: |
| #single | `41.69% <ø> (-0.01%)` | :arrow_down: |

| [Impacted Files](https://codecov.io/gh/pandas-dev/pandas/pull/25420?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [pandas/errors/\_\_init\_\_.py](https://codecov.io/gh/pandas-dev/pandas/pull/25420/diff?src=pr&el=tree#diff-cGFuZGFzL2Vycm9ycy9fX2luaXRfXy5weQ==) | `100% <0%> (ø)` | :arrow_up: |
| [pandas/util/testing.py](https://codecov.io/gh/pandas-dev/pandas/pull/25420/diff?src=pr&el=tree#diff-cGFuZGFzL3V0aWwvdGVzdGluZy5weQ==) | `87.66% <0%> (+0.09%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/25420?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/25420?src=pr&el=footer). Last update [15d8178...a7b602e](https://codecov.io/gh/pandas-dev/pandas/pull/25420?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

Thanks @ThibTrip!