Index repr changes to make them consistent
State: closed

With this PR, makes repr of all Index types consistent. 
closes #6482
closes #6295
replaces #9897

Previous Behavior

```
In [1]: pd.get_option('max_seq_items')
Out[1]: 100

In [2]: pd.Index(range(4),name='foo')
Out[2]: Int64Index([0, 1, 2, 3], dtype='int64')

In [3]: pd.Index(range(104),name='foo')
Out[3]: Int64Index([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, ...], dtype='int64')

In [4]: pd.date_range('20130101',periods=4,name='foo',tz='US/Eastern')
Out[4]: 
<class 'pandas.tseries.index.DatetimeIndex'>
[2013-01-01 00:00:00-05:00, ..., 2013-01-04 00:00:00-05:00]
Length: 4, Freq: D, Timezone: US/Eastern

In [5]: pd.date_range('20130101',periods=104,name='foo',tz='US/Eastern')
Out[5]: 
<class 'pandas.tseries.index.DatetimeIndex'>
[2013-01-01 00:00:00-05:00, ..., 2013-04-14 00:00:00-04:00]
Length: 104, Freq: D, Timezone: US/Eastern
```

New Behavior

```

# this is here just to have a consisten display here, it will normally get the value from the console width
In [1]:   pd.set_option('display.width',100)

In [2]:    pd.Index(range(4),name='foo')
Out[2]: Int64Index([0, 1, 2, 3], dtype='int64', name=u'foo')

In [3]:    pd.Index(range(25),name='foo')
Out[3]: 
Int64Index([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
            24],
           dtype='int64', name=u'foo')

In [4]:    pd.Index(range(104),name='foo')
Out[4]: 
Int64Index([  0,   1,   2,   3,   4,   5,   6,   7,   8,   9, 
            ...
             94,  95,  96,  97,  98,  99, 100, 101, 102, 103],
           dtype='int64', name=u'foo', length=104)

In [5]:    pd.Index(['datetime', 'sA', 'sB', 'sC', 'flow', 'error', 'temp', 'ref', 'a_bit_a_longer_one']*2)
Out[5]: 
Index([u'datetime', u'sA', u'sB', u'sC', u'flow', u'error', u'temp', u'ref', u'a_bit_a_longer_one',
       u'datetime', u'sA', u'sB', u'sC', u'flow', u'error', u'temp', u'ref',
       u'a_bit_a_longer_one'],
      dtype='object')

In [6]:    pd.CategoricalIndex(['a','bb','ccc','dddd'],ordered=True,name='foobar')
Out[6]: CategoricalIndex([u'a', u'bb', u'ccc', u'dddd'], categories=[u'a', u'bb', u'ccc', u'dddd'], ordered=True, name=u'foobar', dtype='category')

In [7]:    pd.CategoricalIndex(['a','bb','ccc','dddd']*10,ordered=True,name='foobar')
Out[7]: 
CategoricalIndex([u'a', u'bb', u'ccc', u'dddd', u'a', u'bb', u'ccc', u'dddd', u'a', u'bb', u'ccc',
                  u'dddd', u'a', u'bb', u'ccc', u'dddd', u'a', u'bb', u'ccc', u'dddd', u'a', u'bb',
                  u'ccc', u'dddd', u'a', u'bb', u'ccc', u'dddd', u'a', u'bb', u'ccc', u'dddd',
                  u'a', u'bb', u'ccc', u'dddd', u'a', u'bb', u'ccc', u'dddd'],
                 categories=[u'a', u'bb', u'ccc', u'dddd'], ordered=True, name=u'foobar', dtype='category')

In [8]:    pd.CategoricalIndex(['a','bb','ccc','dddd']*100,ordered=True,name='foobar')
Out[8]: 
CategoricalIndex([u'a', u'bb', u'ccc', u'dddd', u'a', u'bb', u'ccc', u'dddd', u'a', u'bb', 
                  ...
                  u'ccc', u'dddd', u'a', u'bb', u'ccc', u'dddd', u'a', u'bb', u'ccc', u'dddd'],
                 categories=[u'a', u'bb', u'ccc', u'dddd'], ordered=True, name=u'foobar', dtype='category', length=400)

In [9]:    pd.CategoricalIndex(np.arange(1000),ordered=True,name='foobar')
Out[9]: 
CategoricalIndex([  0,   1,   2,   3,   4,   5,   6,   7,   8,   9, 
                  ...
                  990, 991, 992, 993, 994, 995, 996, 997, 998, 999],
                 categories=[0, 1, 2, 3, 4, 5, 6, 7, ...], ordered=True, name=u'foobar', dtype='category', length=1000)
In [10]:    pd.date_range('20130101',periods=4,name='foo',tz='US/Eastern')
Out[10]: 
DatetimeIndex(['2013-01-01 00:00:00-05:00', '2013-01-02 00:00:00-05:00',
               '2013-01-03 00:00:00-05:00', '2013-01-04 00:00:00-05:00'],
              dtype='datetime64[ns]', name=u'foo', freq='D', tz='US/Eastern')

In [11]:    pd.date_range('20130101',periods=25,name='foo',tz='US/Eastern')
Out[11]: 
DatetimeIndex(['2013-01-01 00:00:00-05:00', '2013-01-02 00:00:00-05:00',
               '2013-01-03 00:00:00-05:00', '2013-01-04 00:00:00-05:00',
               '2013-01-05 00:00:00-05:00', '2013-01-06 00:00:00-05:00',
               '2013-01-07 00:00:00-05:00', '2013-01-08 00:00:00-05:00',
               '2013-01-09 00:00:00-05:00', '2013-01-10 00:00:00-05:00',
               '2013-01-11 00:00:00-05:00', '2013-01-12 00:00:00-05:00',
               '2013-01-13 00:00:00-05:00', '2013-01-14 00:00:00-05:00',
               '2013-01-15 00:00:00-05:00', '2013-01-16 00:00:00-05:00',
               '2013-01-17 00:00:00-05:00', '2013-01-18 00:00:00-05:00',
               '2013-01-19 00:00:00-05:00', '2013-01-20 00:00:00-05:00',
               '2013-01-21 00:00:00-05:00', '2013-01-22 00:00:00-05:00',
               '2013-01-23 00:00:00-05:00', '2013-01-24 00:00:00-05:00',
               '2013-01-25 00:00:00-05:00'],
              dtype='datetime64[ns]', name=u'foo', freq='D', tz='US/Eastern')

In [12]:    pd.date_range('20130101',periods=104,name='foo',tz='US/Eastern')
Out[12]: 
DatetimeIndex(['2013-01-01 00:00:00-05:00', '2013-01-02 00:00:00-05:00',
               '2013-01-03 00:00:00-05:00', '2013-01-04 00:00:00-05:00',
               '2013-01-05 00:00:00-05:00', '2013-01-06 00:00:00-05:00',
               '2013-01-07 00:00:00-05:00', '2013-01-08 00:00:00-05:00',
               '2013-01-09 00:00:00-05:00', '2013-01-10 00:00:00-05:00', 
               ...
               '2013-04-05 00:00:00-04:00', '2013-04-06 00:00:00-04:00',
               '2013-04-07 00:00:00-04:00', '2013-04-08 00:00:00-04:00',
               '2013-04-09 00:00:00-04:00', '2013-04-10 00:00:00-04:00',
               '2013-04-11 00:00:00-04:00', '2013-04-12 00:00:00-04:00',
               '2013-04-13 00:00:00-04:00', '2013-04-14 00:00:00-04:00'],
              dtype='datetime64[ns]', name=u'foo', length=104, freq='D', tz='US/Eastern')
```

Note that `MultiIndex`  are multi-line repr and do no truncate sequences (of e.g. labels), this is consistent with previous versions. (easy to change this though)

```
In [1]: MultiIndex.from_product([list('abcdefg'),range(10)],names=['first','second'])
Out[1]: 
MultiIndex(levels=[[u'a', u'b', u'c', u'd', u'e', u'f', u'g'], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]],
           labels=[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]],
           names=[u'first', u'second'])

```


Labels:
name: Indexing
description: Related to indexing on series/frames, not to indexes themselves
name: Output-Formatting
description: __repr__ of pandas objects, to_string

Comments:
@jorisvandenbossche 
@shoyer 

cc @hsperr 

Looks like a great idea to me! Would be nice to squeeze name into repr for datetimeindex, too.

I think adding the name is certainly OK!

However, I don't know if I like the stacking and indenting under each other. For short indices, this makes your output in the console a lot longer.

If we change the Index repr in such a way, I would do at once a more thourough clean-up, and also look if we can/want to make the DatetimeIndex more consistent (and I would then do this for 0.17 and not in a minor release)

Ah, I see that you updated the initial message :-) (my response was based on the mail I got)

So you also reformatted the datetime-like indices. I think that is a good idea, but to repeat above: maybe we should leave this for 0.17? And I would also ping the mailing list.

And maybe we should also think about if we want a difference between repr and str.

Small remark on the actual output: for DatetimeIndex, the dates should also be quoted I think to have this evalable (like it is for TimedeltaIndex and objext Index)

I do agree with @jorisvandenbossche that it's nice to have the output on one line than spread over many.

As for larger unification of index repr, this is also a great idea! Given that this is unlikely to break any existing code, I think it would _probably_ be OK in an point release (especially given how loosely pandas does semantic versioning already -- people already expect new features and changes in point releases).

My vote would be to include more than the first and last items in string output for all indexes. Perhaps the first 30 and last 30 items, like `Series`? I'd be happy even with just 5/5. This is actually a bit of a pet-peeve of mine with the old `DatetimeIndex` repr -- I would often end up converting the index to a series just to see more than 2 values.

ok, this was pretty trivial (and now the short format works for everything).

`max_seq_items` is for this purpose, but I think need to make much smaller (its a default of 100 now), or maybe adjust a bit, e.g. for integers its ok, but for datetimes its way too big.

so will print short format if its a small sequence, and long format otherwise (trivial to be either one)

```
In [1]: pd.set_option('max_seq_items',8)

In [2]: pd.date_range('20130101',freq='s',periods=2,tz='US/Eastern',name='foo')
Out[2]: DatetimeIndex(['2013-01-01 00:00:00-05:00', '2013-01-01 00:00:01-05:00'], name=u'foo', dtype='datetime64[ns]', length=2, freq='S', tz='US/Eastern')

In [3]: pd.date_range('20130101',freq='s',periods=4,tz='US/Eastern',name='foo')
Out[3]: DatetimeIndex(['2013-01-01 00:00:00-05:00', '2013-01-01 00:00:01-05:00', '2013-01-01 00:00:02-05:00', '2013-01-01 00:00:03-05:00'], name=u'foo', dtype='datetime64[ns]', length=4, freq='S', tz='US/Eastern')

In [4]: pd.date_range('20130101',freq='s',periods=6,tz='US/Eastern',name='foo')
Out[4]: DatetimeIndex(['2013-01-01 00:00:00-05:00', '2013-01-01 00:00:01-05:00', '2013-01-01 00:00:02-05:00', '2013-01-01 00:00:03-05:00', '2013-01-01 00:00:04-05:00', '2013-01-01 00:00:05-05:00'], name=u'foo', dtype='datetime64[ns]', length=6, freq='S', tz='US/Eastern')

In [5]: pd.date_range('20130101',freq='s',periods=8,tz='US/Eastern',name='foo')
Out[5]: DatetimeIndex(['2013-01-01 00:00:00-05:00', '2013-01-01 00:00:01-05:00', '2013-01-01 00:00:02-05:00', '2013-01-01 00:00:03-05:00', '2013-01-01 00:00:04-05:00', '2013-01-01 00:00:05-05:00', '2013-01-01 00:00:06-05:00', '2013-01-01 00:00:07-05:00'], name=u'foo', dtype='datetime64[ns]', length=8, freq='S', tz='US/Eastern')

In [6]: pd.date_range('20130101',freq='s',periods=10,tz='US/Eastern',name='foo')
Out[6]: 
DatetimeIndex(['2013-01-01 00:00:00-05:00', '2013-01-01 00:00:01-05:00', ..., '2013-01-01 00:00:08-05:00', '2013-01-01 00:00:09-05:00'],
              name=u'foo',
              dtype='datetime64[ns]',
              length=10,
              freq='S',
              tz='US/Eastern')
```

```
In [9]: Index(range(8),name='foo')
Out[9]: Int64Index([0, 1, 2, 3, 4, 5, 6, 7], name=u'foo', dtype='int64')

In [10]: Index(range(10),name='foo')
Out[10]: 
Int64Index([0, 1, ..., 8, 9],
           name=u'foo',
           dtype='int64')
```

This is not really much of a change per-se as a) you normally don't print indexes themselves that often. and its just a display fix (and really a bug fix at that).

starting to like these (I changed it to always print on the same line). MultiIndex (and CategoricalIndex) are  the odd one out here, but they have quite a bit more info to communicate

```
In [2]: pd.set_option('max_seq_items',8)

In [3]: pd.date_range('20130101',periods=80)
Out[3]: DatetimeIndex(['2013-01-01', '2013-01-02', ..., '2013-03-20', '2013-03-21'], dtype='datetime64[ns]', length=80, freq='D', tz=None)

In [4]: Index(range(8))
Out[4]: Int64Index([0, 1, 2, 3, 4, 5, 6, 7], dtype='int64')

In [5]: Index(range(10))
Out[5]: Int64Index([0, 1, ..., 8, 9], dtype='int64')

In [6]: Index(range(10),name='foo')
Out[6]: Int64Index([0, 1, ..., 8, 9], name=u'foo', dtype='int64')
```

ok, updated the top of the PR with new/previous behavior.

This unifies all Index repr (including MultiIndex, though that is unchanged and multi-line). I switched back to a single line, with the `display.max_seq_items` controlling if it does a short or long-format. All datetimelike are quoted (so actually a short-repr works, a long-one won't work). 

The number to display in the short-repr is 2 on the head and 2 on the tail and is hard coded, but I suppose could be 'computed', e.g. in theory you could show say more integers that you can datetimes, but will leave that for later.

OK, I would probably default to showing 3 items rather than 2, but this is a step in the right direction.

As long as we're changing this, let's make sure that all index types can be run through eval, at least if they aren't truncated for length. So I think that means the `length` field needs to go.

I would vote for on a single line. The terminal wraps it anyways, and otherwise you can get strange effects like:

```
In [3]: pd.Index(range(21))
Out[3]:
Int64Index([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19
, 20],
           dtype='int64')
```

But should check how this in a notebook.

Some other feedback:
- not sure that the 'name' should go before dtype. It seems more logical to put optional ones as last.
- agree about the `length` field. I know it is there in the current repr, but this is inconsistent with the others, and also not a real correct kwarg.
- it feels strange to me that if you approach `max_seq_items` you can have a very long output, and then at once if you reach it, only a very short output. It seems more logical that the output is truncated at  `max_seq_items` (eg if `max_seq_items` is set at 30, show the first 15 and last 15). But that can be an argument to change the default of `max_seq_items` to a much lower one (or to make this a new option specific for index)

By the way, as this directly touches the output users see (and that can be delicate), I would certainly also bring this to the mailing list. Plus, just having more eyes looking at this as the three of us would be good. I can do it tomorrow, if it is not yet done by then.

we _could_ have an argument say `max_seq_visible` to control the head/tail ones. But honestly I would do that later, see if its really needed.

I just put `name/dtype` (and length only shows up if you are truncating) first. but could easily change that order (you want dtype then name, ok)

If you want to put on the mailing list ok by me. I don't really think this is that big of a deal. The basic formats are pretty much unchanged and its just cleaning up things. (the current PR is for 1 line btw).

top-section is updated

I updated the top of the PR to show the repr of `MultiIndex/CategoricalIndex` (unchanged for MultiIndex from previous versions)

Wouldn't we keep the new `CategoricalIndex` consistent with the other Index types instead of to `MultiIndex`?

@jorisvandenbossche you mean 1 line?

I think things get lost, e.g. `ordered/name`. As you have both codes/categories. Now `codes` themselves are not really necessary (and simliarly for MultiIndex), e.g. in my example a MultiIndex is really just

```
In [7]: MultiIndex.from_product([list('abcdefg'),range(10)],names=['first','second']).levels[0]
Out[7]: Index([u'a', u'b', u'c', u'd', u'e', u'f', u'g'], dtype='object', name=u'first')

In [8]: MultiIndex.from_product([list('abcdefg'),range(10)],names=['first','second']).levels[1]
Out[8]: Int64Index([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], dtype='int64', name=u'second')
```

Which IMHO is more informative, but it would be by-definition multi-line repr

and `CategoricalIndex` is _closer_ to `MultiIndex` I think.

```
In [12]: pd.date_range('20130101',periods=104,name='foo',tz='US/Eastern')
Out[12]:
DatetimeIndex(['2013-01-01 00:00:00-05:00', '2013-01-02 00:00:00-05:00', ...,
               '2013-04-13 00:00:00-04:00', '2013-04-14 00:00:00-04:00'],
              dtype='datetime64[ns]', name=u'foo', length=104, freq='D', tz='US/Eastern')
```

@jorisvandenbossche your proposal looks like adding a line feed after the 'data' portion, then putting all the rest on the next line, yes? 

Can you show what you think for th example above? (the short and long-format)

@shoyer @jorisvandenbossche 

any remaining issues on this?

I think promotes consistency. Can always tweak the format in future versions as its pretty easy to change.

Sorry, I will look at it this evening!

I agree these are good changes -- the old repr was not very consistent.

To understand correclty, everything is now on 1 line? (so it lets the terminal wrap it as needed)

Yes, I think this is OK for now (the other proposal of splitting the values ourselves over multiple lines so they can be nicely aligned as numpy arrays do (proposal from the mailing list) can maybe be added later. Only three things:
- I am still not really fond on the `length` keyword-like (as this is the only one that is not a real keyword). But OK for me if others like this.
- I would personally keep the `max_seq_items` to the same default of 100 for now. 10 is really not much (for dataframes we use 60)
- I would make the CategoricalIndex follow the other Index types (so on one line)

Furthermore, the CategoricalIndex is not following the `max_seq_items` as the other indices?

With the PR:

```
In [34]: pd.CategoricalIndex(np.random.randint(0,5,size=100),name='foo')
Out[34]:
CategoricalIndex([3, 3, 4, 2, 2, 0, 3, 4, 0, 1, 1, 3, 2, 4, 2, 2, 2, 0, 4, 3, 4,
 1, 0, 4, 0, 0, 3, 3, 4, 1, 2, 4, 3, 1, 0, 1, 0, 2, 0, 2, 0, 3, 0, 1, 3, 1, 3, 0
, 2, 4, 3, 1, 1, 0, 0, 3, 0, 3, 2, 3, 1, 4, 1, 3, 2, 2, 0, 0, 1, 1, 1, 1, 0, 4,
3, 1, 3, 0, 3, 1, 4, 4, 4, 4, 3, 3, 1, 2, 4, 3, 1, 3, 0, 2, 2, 2, 0, 4, 1, 1],
                 categories=[0, 1, 2, 3, 4],
                 ordered=False,
                 name=u'foo',
                 dtype='category')
```

The above gives a bit a strange look I find.

Categorical follows exactly the format of MultiIndex
no wrapping of values at all

putting this on 1 line is imho very confusing

why would you make max_seq_items so big? the point is to provide a concise view - how about 20 as a compromise 

- for the categorical: the difference with MultiIndex is that there you don't have 3 extra small lines at the end. It would also be possible to put only these on one line.
  For eg DatetimeIndex, you also have a lot of extra info (freq, tz, dtype, name), and there we put everything on one line
- max_seq_items: for other Index types apart from the datetime-like, it is like that at this moment (showing up to 100 items). And I don't think we got complaints about that? 
  For me personally, one of the annoying things with DatetimeIndex was that it showed only 2 values. With this PR it goes from 2 to 4, which is already better of course! :-), but personally I would like the see more. 
  The fact that with Index of length 10 -> you see 10 items, index of length 11 -> you see 4 items, is also a bit strange. I would also have this 10 / first 5 last 5 (or 20 and first 10 / last 10)

The "what is the point of looking at df.index" is indeed the good question. 
Is it to provide a concise view vs to have a detailed look at the values? Probably people will use it for different purposes.

But regarding to a quick look of what kind of index / what is inside, having a more aligned output will also help (following the numpy array approach a bit). 
For example, the current output of a DatetimeIndex (with this PR):

```
In [42]: pd.date_range('20130101',periods=10,name='foo',tz='US/Eastern')
Out[42]: DatetimeIndex(['2013-01-01 00:00:00-05:00', '2013-01-02 00:00:00-05:00'
, '2013-01-03 00:00:00-05:00', '2013-01-04 00:00:00-05:00', '2013-01-05 00:00:00
-05:00', '2013-01-06 00:00:00-05:00', '2013-01-07 00:00:00-05:00', '2013-01-08 0
0:00:00-05:00', '2013-01-09 00:00:00-05:00', '2013-01-10 00:00:00-05:00'], dtype
='datetime64[ns]', name=u'foo', freq='D', tz='US/Eastern')
```

could be something like:

```
In [42]: pd.date_range('20130101',periods=10,name='foo',tz='US/Eastern')
Out[42]: 
DatetimeIndex(['2013-01-01 00:00:00-05:00', '2013-01-02 00:00:00-05:00',
               '2013-01-03 00:00:00-05:00', '2013-01-04 00:00:00-05:00',
               '2013-01-05 00:00:00-05:00', '2013-01-06 00:00:00-05:00',
               '2013-01-07 00:00:00-05:00', '2013-01-08 00:00:00-05:00',
               '2013-01-09 00:00:00-05:00', '2013-01-10 00:00:00-05:00'],
              dtype='datetime64[ns]', name=u'foo', freq='D', tz='US/Eastern')
```

@jreback my doubt about the `max_seq_len` is maybe more about the 2x2 values that are shown (instead of 2x5), than the value of 10 itself. You can always do  `.values` if you want to see all values

ok I changes `max_seq_items` to 20, and now use +-5 for the head/tail. and CategoricalIndex is now on 1-line.

```
In [3]: pd.date_range('20130101',periods=50,freq='s',name='foo')
Out[3]: DatetimeIndex(['2013-01-01 00:00:00', '2013-01-01 00:00:01', '2013-01-01 00:00:02', '2013-01-01 00:00:03', '2013-01-01 00:00:04', ..., '2013-01-01 00:00:45', '2013-01-01 00:00:46', '2013-01-01 00:00:47', '2013-01-01 00:00:48', '2013-01-01 00:00:49'], dtype='datetime64[ns]', name=u'foo', length=50, freq='S', tz=None)

In [4]: pd.date_range('20130101',periods=10,freq='s',name='foo')
Out[4]: DatetimeIndex(['2013-01-01 00:00:00', '2013-01-01 00:00:01', '2013-01-01 00:00:02', '2013-01-01 00:00:03', '2013-01-01 00:00:04', '2013-01-01 00:00:05', '2013-01-01 00:00:06', '2013-01-01 00:00:07', '2013-01-01 00:00:08', '2013-01-01 00:00:09'], dtype='datetime64[ns]', name=u'foo', freq='S', tz=None)

In [5]: pd.CategoricalIndex(list('aabbcdefg')*2,ordered=True,name='foo')
Out[5]: CategoricalIndex([u'a', u'a', u'b', u'b', u'c', u'd', u'e', u'f', u'g', u'a', u'a', u'b', u'b', u'c', u'd', u'e', u'f', u'g'], categories=[u'a', u'b', u'c', u'd', u'e', u'f', u'g'], ordered=True, name=u'foo', dtype='category')

In [6]: pd.CategoricalIndex(list('aabbcdefg')*10,ordered=True,name='foo')
Out[6]: CategoricalIndex([u'a', u'a', u'b', u'b', u'c', ..., u'c', u'd', u'e', u'f', u'g'], categories=[u'a', u'b', u'c', u'd', u'e', u'f', u'g'], ordered=True, name=u'foo', dtype='category')

In [8]: Index(range(22),name='foo')
Out[8]: Int64Index([0, 1, 2, 3, 4, ..., 17, 18, 19, 20, 21], dtype='int64', name=u'foo', length=22)

In [9]: Index(range(10),name='foo')
Out[9]: Int64Index([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], dtype='int64', name=u'foo')
```

This was easy actually. Only for the time-base ones (Period/Datetime/Timedelta).
[3] and [4] ok?

```
In [1]: pd.date_range('20130101',periods=30,freq='s',name='foo')
Out[1]: 
DatetimeIndex(['2013-01-01 00:00:00',
               '2013-01-01 00:00:01',
               '2013-01-01 00:00:02',
               '2013-01-01 00:00:03',
               '2013-01-01 00:00:04',
               '2013-01-01 00:00:05'
               ...
               '2013-01-01 00:00:24',
               '2013-01-01 00:00:25',
               '2013-01-01 00:00:26',
               '2013-01-01 00:00:27',
               '2013-01-01 00:00:28',
               '2013-01-01 00:00:29'
              ], dtype='datetime64[ns]', name=u'foo', length=30, freq='S', tz=None)

In [2]: pd.date_range('20130101',periods=10,freq='s',name='foo')
Out[2]: 
DatetimeIndex(['2013-01-01 00:00:00',
               '2013-01-01 00:00:01',
               '2013-01-01 00:00:02',
               '2013-01-01 00:00:03',
               '2013-01-01 00:00:04',
               '2013-01-01 00:00:05',
               '2013-01-01 00:00:06',
               '2013-01-01 00:00:07',
               '2013-01-01 00:00:08',
               '2013-01-01 00:00:09'
              ], dtype='datetime64[ns]', name=u'foo', freq='S', tz=None)

In [3]: pd.date_range('20130101',periods=2,freq='s',name='foo')
Out[3]: DatetimeIndex(['2013-01-01 00:00:00', '2013-01-01 00:00:01'], dtype='datetime64[ns]', name=u'foo', freq='S', tz=None)

In [4]: pd.date_range('20130101',periods=1,freq='s',name='foo')
Out[4]: DatetimeIndex(['2013-01-01'], dtype='datetime64[ns]', name=u'foo', freq='S', tz=None)
```