Repository: pandas-dev/pandas

Issue:
BUG: DataFrame.loc[*, label] fails with IntervalIndex
#### Code Sample, a copy-pastable example if possible
Setup:
```python
In [2]: ii = pd.interval_range(0, 4)

In [3]: df = pd.DataFrame(np.arange(12).reshape(4, 3), index=ii, columns=list('ABC'))

In [4]: df
Out[4]:
        A   B   C
(0, 1]  0   1   2
(1, 2]  3   4   5
(2, 3]  6   7   8
(3, 4]  9  10  11
```
Scalar and `Interval` objects raise an `AttributeError`:

```python
In [5]: df.loc[0.5, 'A']
---------------------------------------------------------------------------
AttributeError: 'pandas._libs.interval.IntervalTree' object has no attribute 'get_value'

In [6]: df.loc[pd.Interval(0, 1), 'A']
---------------------------------------------------------------------------
AttributeError: 'pandas._libs.interval.IntervalTree' object has no attribute 'get_value'
```
It works fine if column labels aren't passed, or if a list-like is passed:
```python
In [7]: df.loc[0.5]
Out[7]:
A    0
B    1
C    2
Name: (0, 1], dtype: int32

In [8]: df.loc[pd.Interval(0, 1)]
Out[8]:
A    0
B    1
C    2
Name: (0, 1], dtype: int32

In [9]: df.loc[0.5, ['A']]
Out[9]:
A    0
Name: (0, 1], dtype: int32

In [10]: df.loc[pd.Interval(0, 1), ['B', 'C']]
Out[10]:
B    1
C    2
Name: (0, 1], dtype: int32
```

#### Problem description
Indexing with `loc` fails.

#### Expected Output
I'd expect `loc` to return the appropriate value.

#### Output of ``pd.show_versions()``

<details>

INSTALLED VERSIONS
------------------
commit: 0bfb61b2114769a29972ef90098c6dda005dbd23
python: 3.6.1.final.0
python-bits: 64
OS: Windows
OS-release: 10
machine: AMD64
processor: Intel64 Family 6 Model 78 Stepping 3, GenuineIntel
byteorder: little
LC_ALL: None
LANG: None
LOCALE: None.None

pandas: 0.23.0.dev0+422.g0bfb61b
pytest: 3.1.2
pip: 9.0.1
setuptools: 27.2.0
Cython: 0.25.2
numpy: 1.13.3
scipy: 1.0.0
pyarrow: 0.6.0
xarray: 0.9.6
IPython: 6.1.0
sphinx: 1.5.6
patsy: 0.4.1
dateutil: 2.6.0
pytz: 2017.2
blosc: None
bottleneck: None
tables: 3.4.2
numexpr: 2.6.4
feather: 0.4.0
matplotlib: 2.0.2
openpyxl: 2.4.8
xlrd: 1.1.0
xlwt: 1.3.0
xlsxwriter: 0.9.8
lxml: 3.8.0
bs4: None
html5lib: 0.999
sqlalchemy: 1.1.13
pymysql: None
psycopg2: None
jinja2: 2.9.6
s3fs: None
fastparquet: 0.1.0
pandas_gbq: None
pandas_datareader: None

</details>



Discussion:
Indexing with `IntervalIndex` is unusual, but this indeed should not crash.  Patch and PR are welcome!
Hi, I'm going to work on this issue this weekend.

Resolving patch:
diff --git a/pandas/core/indexing.py b/pandas/core/indexing.py
--- a/pandas/core/indexing.py
+++ b/pandas/core/indexing.py
@@ -1491,7 +1491,7 @@ def __getitem__(self, key):
             try:
                 if self._is_scalar_access(key):
                     return self._getitem_scalar(key)
-            except (KeyError, IndexError):
+            except (KeyError, IndexError, AttributeError):
                 pass
             return self._getitem_tuple(key)
         else:


Test patch:
diff --git a/pandas/tests/frame/test_indexing.py b/pandas/tests/frame/test_indexing.py
--- a/pandas/tests/frame/test_indexing.py
+++ b/pandas/tests/frame/test_indexing.py
@@ -3099,6 +3099,28 @@ def test_type_error_multiindex(self):
         result = dg['x', 0]
         assert_series_equal(result, expected)
 
+    def test_interval_index(self):
+        # GH 19977
+        index = pd.interval_range(start=0, periods=3)
+        df = pd.DataFrame([[1, 2, 3], [4, 5, 6], [7, 8, 9]],
+                          index=index,
+                          columns=['A', 'B', 'C'])
+
+        expected = 1
+        result = df.loc[0.5, 'A']
+        assert_almost_equal(result, expected)
+
+        index = pd.interval_range(start=0, periods=3, closed='both')
+        df = pd.DataFrame([[1, 2, 3], [4, 5, 6], [7, 8, 9]],
+                          index=index,
+                          columns=['A', 'B', 'C'])
+
+        index_exp = pd.interval_range(start=0, periods=2,
+                                      freq=1, closed='both')
+        expected = pd.Series([1, 4], index=index_exp, name='A')
+        result = df.loc[1, 'A']
+        assert_series_equal(result, expected)
+
 
 class TestDataFrameIndexingDatetimeWithTZ(TestData):