Repository: pandas-dev/pandas

Issue:
BUG: pandas.tools.util.cartesian_product doesn't work on DatetimeIndex objects
This breaks the new `pandas.MultiIndex.from_product` function when one of the product arrays is DatetimeIndex. Observe:

```
>>> import pandas as pd
>>> from pandas.tools.util import cartesian_product
>>> x, y = cartesian_product([[1, 2], pd.date_range('2000-01-01', periods=2)])
>>> print x
[1 1 2 2]
>>> print y.values
['1999-12-31T16:00:00.000000000-0800' '1999-12-31T16:00:00.000000000-0800'
 '2000-01-01T16:00:00.000000000-0800' '2000-01-01T16:00:00.000000000-0800']
```

If `cartesian_product` was working properly, the dates should actually be [1999, 2000, 1999, 2000].

The simple fix would be to convert everything into a numpy array before calculating the cartesian product.



Discussion:
```
In [3]: MultiIndex.from_product([[1, 2], pd.date_range('2000-01-01', periods=2)]).values
Out[3]: 
array([(1, Timestamp('2000-01-01 00:00:00', tz=None)),
       (1, Timestamp('2000-01-01 00:00:00', tz=None)),
       (2, Timestamp('2000-01-02 00:00:00', tz=None)),
       (2, Timestamp('2000-01-02 00:00:00', tz=None))], dtype=object)

In [4]: from pandas.tools.util import cartesian_product

In [5]: >>> x, y = cartesian_product([[1, 2], pd.date_range('2000-01-01', periods=2)])

In [6]: x
Out[6]: array([1, 1, 2, 2])

In [7]: y
Out[7]: 
<class 'pandas.tseries.index.DatetimeIndex'>
[2000-01-01, ..., 2000-01-02]
Length: 4, Freq: None, Timezone: None

In [8]: y.values
Out[8]: 
array(['1999-12-31T19:00:00.000000000-0500',
       '1999-12-31T19:00:00.000000000-0500',
       '2000-01-01T19:00:00.000000000-0500',
       '2000-01-01T19:00:00.000000000-0500'], dtype='datetime64[ns]')
```

looks ok to me, what is the problem?

It's the order that is not OK:

```
In [22]: x, y = cartesian_product([[1, 2], pd.date_range('2000-01-01', periods=2)])
In [23]: x
Out[23]: array([1, 1, 2, 2])
In [25]: y.day
Out[25]: array([1, 1, 2, 2], dtype=int64)

In [26]: x, y = cartesian_product([[1, 2], [1,2]])
In [28]: x
Out[28]: array([1, 1, 2, 2])
In [29]: y
Out[29]: array([1, 2, 1, 2])
```

See difference between `y.day` in first case and `y` in second case.

ahh....I c...ok marking as a bug

@shoyer pull-request for this? 

Sure - I'll send something in tomorrow or Monday.

On Sat, Feb 22, 2014 at 6:18 AM, jreback notifications@github.com wrote:

> ## @shoyer pull-request for this? 
> 
> Reply to this email directly or view it on GitHub:
> https://github.com/pydata/pandas/issues/6439#issuecomment-35803589


Resolving patch:
diff --git a/pandas/tools/util.py b/pandas/tools/util.py
--- a/pandas/tools/util.py
+++ b/pandas/tools/util.py
@@ -29,7 +29,7 @@ def cartesian_product(X):
 
     b = cumprodX[-1] / cumprodX
 
-    return [np.tile(np.repeat(x, b[i]),
+    return [np.tile(np.repeat(np.asarray(x), b[i]),
                     np.product(a[i]))
                for i, x in enumerate(X)]
 


Test patch:
diff --git a/pandas/tools/tests/test_util.py b/pandas/tools/tests/test_util.py
--- a/pandas/tools/tests/test_util.py
+++ b/pandas/tools/tests/test_util.py
@@ -6,6 +6,7 @@
 import numpy as np
 from numpy.testing import assert_equal
 
+import pandas
 import pandas.util.testing as tm
 from pandas.tools.util import cartesian_product
 
@@ -23,6 +24,13 @@ def test_simple(self):
                     np.array([ 1, 22,  1, 22,  1, 22])]
         assert_equal(result, expected)
 
+    def test_datetimeindex(self):
+        # regression test for GitHub issue #6439
+        x = pandas.date_range('2000-01-01', periods=2)
+        result = [pandas.Index(y).day for y in cartesian_product([x, x])]
+        expected = [np.array([1, 1, 2, 2]), np.array([1, 2, 1, 2])]
+        assert_equal(result, expected)
+
 
 class TestLocaleUtils(tm.TestCase):