Repository: pandas-dev/pandas

Issue:
ER: Bug accessing a series MultiIndex with a Timestamp
I have a series with a multiindex (datetime, int).
When I try to access a slice corresponding to a date using a Timestamp I have an exception printed to screen if the size of the series is >= 1e6.
No problem if I access the same slice with a string.
No problem with an equivalent dataframe.
Tested on 0.10.1 and 0.11, I'm sorry but I don't have access to 0.12rc1.

``` python

In [1]: import pandas as pd

In [2]: pd.__version__
Out[2]: '0.11.0'

In [3]: np.__version__
Out[3]: '1.7.1'

In [4]: df = pd.DataFrame(randn(1000, 1000), index=pd.date_range('2000-1-1', periods=1000))

In [5]: s = df.stack() # s has 1e6 lines

In [6]: s.head()
Out[6]:
2000-01-01  0   -0.555228
            1   -0.152952
            2    0.401490
            3   -1.057106
            4   -0.987895
dtype: float64

In [7]: s['2000-1-4'].head()
Out[7]:
0   -1.009647
1    0.094427
2    0.105180
3   -2.166810
4   -0.767165
dtype: float64

In [8]: s[pd.Timestamp('2000-1-4')].head()
Exception TypeError: TypeError('Cannot compare Timestamp with (<Timestamp: 2002-09-26 00:00:00>, 999)',) in 'pandas.index._bin_search' ignored
Out[8]:
0   -1.009647
1    0.094427
2    0.105180
3   -2.166810
4   -0.767165
dtype: float64

In [9]: s2 = s[:-1].copy() # s2 has 1e6 - 1 lines

In [10]: s2['2000-1-4'].head()
Out[10]:
0   -1.009647
1    0.094427
2    0.105180
3   -2.166810
4   -0.767165
dtype: float64

In [11]: s2[pd.Timestamp('2000-1-4')].head()
Out[11]:
0   -1.009647
1    0.094427
2    0.105180
3   -2.166810
4   -0.767165
dtype: float64

In [12]: df2 = pd.DataFrame(s)

In [13]: df2.ix['2000-1-4'].head()
Out[13]:
          0
0 -1.009647
1  0.094427
2  0.105180
3 -2.166810
4 -0.767165

In [14]: df2.ix[pd.Timestamp('2000-1-4')].head()
Out[14]:
          0
0 -1.009647
1  0.094427
2  0.105180
3 -2.166810
4 -0.767165

```



Discussion:
I get slightly less (more?) informative error message on `master`

```
In [11]: s[pd.Timestamp('2000-1-4')].head()
Exception TypeError: TypeError("Cannot compare Timestamp with 'tuple'",) in 'pandas.index._bin_search' ignored
Out[11]:
0   -0.834
1    0.374
2    0.755
3    1.747
4    0.366
dtype: float64
```

but it's still the same issue.

ok....so on the timestamp it is raising (but being caught) and continues...weird....marking as an error reporting bug

Indeed, why doesn't this raise "for real"?

`_bin_search` is not propagating errors it generates

here's why: http://docs.cython.org/src/userguide/language_basics.html#error-return-values


Resolving patch:
diff --git a/pandas/core/index.py b/pandas/core/index.py
--- a/pandas/core/index.py
+++ b/pandas/core/index.py
@@ -1,4 +1,5 @@
 # pylint: disable=E1101,E1103,W0232
+import datetime
 from functools import partial
 from pandas.compat import range, zip, lrange, lzip, u
 from pandas import compat
@@ -2224,16 +2225,20 @@ def get_value(self, series, key):
         # Label-based
         s = _values_from_object(series)
         k = _values_from_object(key)
+
+        def _try_mi(k):
+            # TODO: what if a level contains tuples??
+            loc = self.get_loc(k)
+            new_values = series.values[loc]
+            new_index = self[loc]
+            new_index = _maybe_droplevels(new_index, k)
+            return Series(new_values, index=new_index, name=series.name)
+
         try:
             return self._engine.get_value(s, k)
         except KeyError as e1:
             try:
-                # TODO: what if a level contains tuples??
-                loc = self.get_loc(key)
-                new_values = series.values[loc]
-                new_index = self[loc]
-                new_index = _maybe_droplevels(new_index, key)
-                return Series(new_values, index=new_index, name=series.name)
+                return _try_mi(key)
             except KeyError:
                 pass
 
@@ -2250,6 +2255,16 @@ def get_value(self, series, key):
             except Exception:  # pragma: no cover
                 raise e1
         except TypeError:
+
+            # a Timestamp will raise a TypeError in a multi-index
+            # rather than a KeyError, try it here
+            if isinstance(key, (datetime.datetime,np.datetime64)) or (
+                compat.PY3 and isinstance(key, compat.string_types)):
+                try:
+                    return _try_mi(Timestamp(key))
+                except:
+                    pass
+
             raise InvalidIndexError(key)
 
     def get_level_values(self, level):
@@ -2779,6 +2794,7 @@ def reindex(self, target, method=None, level=None, limit=None,
         if level is not None:
             if method is not None:
                 raise TypeError('Fill method not supported if level passed')
+            target = _ensure_index(target)
             target, indexer, _ = self._join_level(target, level, how='right',
                                                   return_indexers=True)
         else:


Test patch:
diff --git a/pandas/tseries/tests/test_timeseries.py b/pandas/tseries/tests/test_timeseries.py
--- a/pandas/tseries/tests/test_timeseries.py
+++ b/pandas/tseries/tests/test_timeseries.py
@@ -2751,6 +2751,24 @@ def f():
             df_multi.loc[('2013-06-19', 'ACCT1', 'ABC')]
         self.assertRaises(KeyError, f)
 
+        # GH 4294
+        # partial slice on a series mi
+        s = pd.DataFrame(randn(1000, 1000), index=pd.date_range('2000-1-1', periods=1000)).stack()
+
+        s2 = s[:-1].copy()
+        expected = s2['2000-1-4']
+        result = s2[pd.Timestamp('2000-1-4')]
+        assert_series_equal(result, expected)
+
+        result = s[pd.Timestamp('2000-1-4')]
+        expected = s['2000-1-4']
+        assert_series_equal(result, expected)
+
+        df2 = pd.DataFrame(s)
+        expected = df2.ix['2000-1-4']
+        result = df2.ix[pd.Timestamp('2000-1-4')]
+        assert_frame_equal(result, expected)
+
     def test_date_range_normalize(self):
         snap = datetime.today()
         n = 50