Skip to content

Commit e44f65b

Browse files
committed
BUG/OUTPUT: fix repring of MI nat
Fix neg indexers in datetimeindex
1 parent f69ff12 commit e44f65b

File tree

6 files changed

+39
-12
lines changed

6 files changed

+39
-12
lines changed

doc/source/v0.14.1.txt

+4
Original file line numberDiff line numberDiff line change
@@ -214,3 +214,7 @@ Bug Fixes
214214
- Bug in ``.ix`` getitem should always return a Series (:issue:`7150`)
215215
- Bug in multi-index slicing with incomplete indexers (:issue:`7399`)
216216
- Bug in multi-index slicing with a step in a sliced level (:issue:`7400`)
217+
- Bug where negative indexers in ``DatetimeIndex`` were not correctly sliced
218+
(:issue:`7408`)
219+
- Bug where ``NaT`` wasn't repr'd correctly in a ``MultiIndex`` (:issue:`7406`,
220+
:issue:`7409`).

pandas/core/index.py

+14-3
Original file line numberDiff line numberDiff line change
@@ -2610,12 +2610,14 @@ def get_level_values(self, level):
26102610
return values
26112611

26122612
def format(self, space=2, sparsify=None, adjoin=True, names=False,
2613-
na_rep='NaN', formatter=None):
2613+
na_rep=None, formatter=None):
26142614
if len(self) == 0:
26152615
return []
26162616

26172617
stringified_levels = []
26182618
for lev, lab in zip(self.levels, self.labels):
2619+
na = na_rep if na_rep is not None else _get_na_rep(lev.dtype.type)
2620+
26192621
if len(lev) > 0:
26202622

26212623
formatted = lev.take(lab).format(formatter=formatter)
@@ -2624,12 +2626,12 @@ def format(self, space=2, sparsify=None, adjoin=True, names=False,
26242626
mask = lab == -1
26252627
if mask.any():
26262628
formatted = np.array(formatted, dtype=object)
2627-
formatted[mask] = na_rep
2629+
formatted[mask] = na
26282630
formatted = formatted.tolist()
26292631

26302632
else:
26312633
# weird all NA case
2632-
formatted = [com.pprint_thing(na_rep if isnull(x) else x,
2634+
formatted = [com.pprint_thing(na if isnull(x) else x,
26332635
escape_chars=('\t', '\r', '\n'))
26342636
for x in com.take_1d(lev.values, lab)]
26352637
stringified_levels.append(formatted)
@@ -4041,3 +4043,12 @@ def _all_indexes_same(indexes):
40414043
if not first.equals(index):
40424044
return False
40434045
return True
4046+
4047+
4048+
def _get_na_rep(dtype):
4049+
return {np.datetime64: 'NaT', np.timedelta64: 'NaT'}.get(dtype, 'NaN')
4050+
4051+
4052+
def _get_na_value(dtype):
4053+
return {np.datetime64: tslib.NaT, np.timedelta64: tslib.NaT}.get(dtype,
4054+
np.nan)

pandas/core/reshape.py

+8-8
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,7 @@
1717
import pandas.core.common as com
1818
import pandas.algos as algos
1919

20-
from pandas.core.index import Index, MultiIndex
21-
from pandas.tseries.period import PeriodIndex
20+
from pandas.core.index import MultiIndex, _get_na_value
2221

2322

2423
class _Unstacker(object):
@@ -83,7 +82,7 @@ def __init__(self, values, index, level=-1, value_columns=None):
8382

8483
def _make_index(lev, lab):
8584
values = _make_index_array_level(lev.values, lab)
86-
i = lev._simple_new(values, lev.name,
85+
i = lev._simple_new(values, lev.name,
8786
freq=getattr(lev, 'freq', None),
8887
tz=getattr(lev, 'tz', None))
8988
return i
@@ -262,7 +261,7 @@ def _make_index_array_level(lev, lab):
262261

263262
l = np.arange(len(lab))
264263
mask_labels = np.empty(len(mask[mask]), dtype=object)
265-
mask_labels.fill(np.nan)
264+
mask_labels.fill(_get_na_value(lev.dtype.type))
266265
mask_indexer = com._ensure_int64(l[mask])
267266

268267
labels = lev
@@ -638,7 +637,7 @@ def melt(frame, id_vars=None, value_vars=None,
638637
639638
This function is useful to massage a DataFrame into a format where one
640639
or more columns are identifier variables (`id_vars`), while all other
641-
columns, considered measured variables (`value_vars`), are "unpivoted" to
640+
columns, considered measured variables (`value_vars`), are "unpivoted" to
642641
the row axis, leaving just two non-identifier columns, 'variable' and
643642
'value'.
644643
@@ -680,7 +679,7 @@ def melt(frame, id_vars=None, value_vars=None,
680679
0 a B 1
681680
1 b B 3
682681
2 c B 5
683-
682+
684683
>>> pd.melt(df, id_vars=['A'], value_vars=['B', 'C'])
685684
A variable value
686685
0 a B 1
@@ -702,7 +701,7 @@ def melt(frame, id_vars=None, value_vars=None,
702701
If you have multi-index columns:
703702
704703
>>> df.columns = [list('ABC'), list('DEF')]
705-
>>> df
704+
>>> df
706705
A B C
707706
D E F
708707
0 a 1 2
@@ -901,7 +900,7 @@ def get_var_names(df, regex):
901900
return df.filter(regex=regex).columns.tolist()
902901

903902
def melt_stub(df, stub, i, j):
904-
varnames = get_var_names(df, "^"+stub)
903+
varnames = get_var_names(df, "^" + stub)
905904
newdf = melt(df, id_vars=i, value_vars=varnames, value_name=stub,
906905
var_name=j)
907906
newdf_j = newdf[j].str.replace(stub, "")
@@ -971,6 +970,7 @@ def get_dummies(data, prefix=None, prefix_sep='_', dummy_na=False):
971970
972971
Examples
973972
--------
973+
>>> import pandas as pd
974974
>>> s = pd.Series(list('abca'))
975975
976976
>>> get_dummies(s)

pandas/lib.pyx

+1-1
Original file line numberDiff line numberDiff line change
@@ -576,7 +576,7 @@ def maybe_indices_to_slice(ndarray[int64_t] indices):
576576
cdef:
577577
Py_ssize_t i, n = len(indices)
578578

579-
if n == 0:
579+
if not n or indices[0] < 0:
580580
return indices
581581

582582
for i in range(1, n):

pandas/tests/test_frame.py

+7
Original file line numberDiff line numberDiff line change
@@ -11665,6 +11665,13 @@ def test_unstack_non_unique_index_names(self):
1166511665
with tm.assertRaises(ValueError):
1166611666
df.T.stack('c1')
1166711667

11668+
def test_repr_with_mi_nat(self):
11669+
df = DataFrame({'X': [1, 2]},
11670+
index=[[pd.NaT, pd.Timestamp('20130101')], ['a', 'b']])
11671+
res = repr(df)
11672+
exp = ' X\nNaT a 1\n2013-01-01 b 2'
11673+
nose.tools.assert_equal(res, exp)
11674+
1166811675
def test_reset_index(self):
1166911676
stacked = self.frame.stack()[::2]
1167011677
stacked = DataFrame({'foo': stacked, 'bar': stacked})

pandas/tests/test_index.py

+5
Original file line numberDiff line numberDiff line change
@@ -873,6 +873,11 @@ def test_outer_join_sort(self):
873873
expected = right_idx.astype(object).union(left_idx.astype(object))
874874
tm.assert_index_equal(joined, expected)
875875

876+
def test_nan_first_take_datetime(self):
877+
idx = Index([pd.NaT, Timestamp('20130101'), Timestamp('20130102')])
878+
res = idx.take([-1, 0, 1])
879+
exp = Index([idx[-1], idx[0], idx[1]])
880+
tm.assert_index_equal(res, exp)
876881

877882
class TestFloat64Index(tm.TestCase):
878883
_multiprocess_can_split_ = True

0 commit comments

Comments
 (0)