Code Sample, a copy-pastable example if possible

import pandas
import numpy

df = pandas.DataFrame({'A': list(range(6)), 'B': list(range(6))},
                      index=pandas.MultiIndex.from_product(
                                                            [[numpy.datetime64('2017-10-10'), numpy.datetime64('2017-10-11')], range(3)],
                                                            names=['date', 'count']),
                      )

# inconsitency 1: drop level
print(df.loc[('2017-10-10')])
print(df.loc[(numpy.datetime64('2017-10-10'))])

# inconsitency 2: DataFrame or Series
print(df.loc[('2017-10-10', 1), :])
print(df.loc[('2017-10-10', 1)])

# inconsistency 3: raises TypeError
try:
    print(df.loc[(numpy.datetime64('2017-10-10'), 1)])
except TypeError as e:
    print(e)
try:
    print(df.loc[(slice('2017-10-10'), slice(1))])
except TypeError as e:
    print(e)

# workaround
# inconsitency 1: drop level
print(df.loc[(slice('2017-10-10'))])
print(df.loc[(slice(numpy.datetime64('2017-10-10')))])

# inconsitency 2: DataFrame or Series
print(df.loc[(slice('2017-10-10'), slice(1)), :])

# inconsistency 3: raises TypeError
print(df.loc[(slice(numpy.datetime64('2017-10-10')), slice(1)), :])

Problem description

When DataFrame (or Series) has a MultiIndex containing numpy.datetime64 in one of the levels, slicing with loc shows inconsistent behaviour. I haven't tested if these inconsistencies are specific to numpy.datetime64 or if they are are also present when using other date formats.

In my view, the output format of loc should not depend on the format of the slice.

Expected Output

It's not up to me to decide on the correct output format but they should be equal, independent of the slice format. Ideally it's the ouput generated in the 'workaround' section.

Output of pd.show_versions()

INSTALLED VERSIONS ------------------ commit: None python: 3.6.2.candidate.1 python-bits: 64 OS: Windows OS-release: 7 machine: AMD64 processor: Intel64 Family 6 Model 60 Stepping 3, GenuineIntel byteorder: little LC_ALL: None LANG: en_US.UTF-8 LOCALE: None.None pandas: 0.21.0 pytest: None pip: 9.0.1 setuptools: 32.3.1 Cython: 0.26.1 numpy: 1.13.3 scipy: 1.0.0 pyarrow: None xarray: 0.10.0 IPython: None sphinx: None patsy: None dateutil: 2.6.0 pytz: 2017.2 blosc: None bottleneck: None tables: 3.4.2 numexpr: 2.6.2 feather: None matplotlib: 2.0.2 openpyxl: 2.4.8 xlrd: 1.0.0 xlwt: None xlsxwriter: None lxml: None bs4: None html5lib: None sqlalchemy: None pymysql: None psycopg2: None jinja2: None s3fs: None fastparquet: None pandas_gbq: None pandas_datareader: None

Comment From: jreback

please read the docs: http://pandas.pydata.org/pandas-docs/stable/timeseries.html#indexing

a string is a slice, while an actual datetime (be it a Timestamp, np.datetime64 etc) is a point in time.

you are passing different kinds of slicing, pandas returns you different output shapes

Here are ways to slice w/o dropping levels.

In [6]: df.loc[[numpy.datetime64('2017-10-10')]]
Out[6]: 
                  A  B
date       count      
2017-10-10 0      0  0
           1      1  1
           2      2  2

In [9]: df.loc[numpy.datetime64('2017-10-10'):np.datetime64('2017-10-10 12:00:00')]
Out[9]: 
                  A  B
date       count      
2017-10-10 0      0  0
           1      1  1
           2      2  2

Comment From: jreback

if you claim an inconsistency you will have to show how this is not documented and/or violates the currently rules as I referenced.