Repository: pandas-dev/pandas

Issue:
API: Reshaping Series to its own shape raises TypeError
This may be seen like a weird function call but it is actually triggered when plotting with development versions of matplotlib and the case is explicitly (and wrongly as it seems) by pandas:

```
>>> import pandas as pd
>>> x = pd.Series(range(5))
>>> x.reshape(x.shape)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/pymodules/python2.7/pandas/core/series.py", line 981, in reshape
    return ndarray.reshape(self, newshape, order)
TypeError: an integer is required
```

It is easily fixed just replacing the offending line by this one:

`return ndarray.reshape(self, newshape, order=order)`

API: Reshaping Series to its own shape raises TypeError
This may be seen like a weird function call but it is actually triggered when plotting with development versions of matplotlib and the case is explicitly (and wrongly as it seems) by pandas:

```
>>> import pandas as pd
>>> x = pd.Series(range(5))
>>> x.reshape(x.shape)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/pymodules/python2.7/pandas/core/series.py", line 981, in reshape
    return ndarray.reshape(self, newshape, order)
TypeError: an integer is required
```

It is easily fixed just replacing the offending line by this one:

`return ndarray.reshape(self, newshape, order=order)`



Discussion:
actually....this should be changed entirely; something like this:

```
if not isinstance(newshape, tuple):
  newshape = tuple([ newshape ])
if newshape == self.shape:
      return self
return self.values.reshape(newshape,order=order)
```

IOW a reshape that does nothing is ok, other wise you get back an `ndarray`

a Series is by definition a 1-D object

The current implementation (with the change I proposed) behaves well AFAICS:

```
>>> import pandas as pd
>>> s = pd.Series(range(4))
>>> s.reshape((4,))
0    0
1    1
2    2
3    3
dtype: int64
>>> s.reshape(4)
0    0
1    1
2    2
3    3
dtype: int64
>>> s.reshape((2, 2))
array([[0, 1],
       [2, 3]])
>>> s.reshape(3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/pymodules/python2.7/pandas/core/series.py", line 981, in reshape
    return ndarray.reshape(self, newshape, order=order)
ValueError: total size of new array must be unchanged
>>> s.reshape((3,))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/pymodules/python2.7/pandas/core/series.py", line 981, in reshape
    return ndarray.reshape(self, newshape, order=order)
ValueError: total size of new array must be unchanged
```

and is pretty clear to me, except for the order check at the beginning which is irrelevant for my use cases.

But yours passes these same tests so I would be happy with it and I think matplotlib would be as well.

I think the order is just for compat with numpy
I agree not that useful
want to so a pull request for this change?

Nitpicky: why not just add a comma at end instead of passing list to tuple
constructor?

https://github.com/pydata/pandas/pull/4659

actually....this should be changed entirely; something like this:

```
if not isinstance(newshape, tuple):
  newshape = tuple([ newshape ])
if newshape == self.shape:
      return self
return self.values.reshape(newshape,order=order)
```

IOW a reshape that does nothing is ok, other wise you get back an `ndarray`

a Series is by definition a 1-D object

The current implementation (with the change I proposed) behaves well AFAICS:

```
>>> import pandas as pd
>>> s = pd.Series(range(4))
>>> s.reshape((4,))
0    0
1    1
2    2
3    3
dtype: int64
>>> s.reshape(4)
0    0
1    1
2    2
3    3
dtype: int64
>>> s.reshape((2, 2))
array([[0, 1],
       [2, 3]])
>>> s.reshape(3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/pymodules/python2.7/pandas/core/series.py", line 981, in reshape
    return ndarray.reshape(self, newshape, order=order)
ValueError: total size of new array must be unchanged
>>> s.reshape((3,))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/pymodules/python2.7/pandas/core/series.py", line 981, in reshape
    return ndarray.reshape(self, newshape, order=order)
ValueError: total size of new array must be unchanged
```

and is pretty clear to me, except for the order check at the beginning which is irrelevant for my use cases.

But yours passes these same tests so I would be happy with it and I think matplotlib would be as well.

I think the order is just for compat with numpy
I agree not that useful
want to so a pull request for this change?

Nitpicky: why not just add a comma at end instead of passing list to tuple
constructor?

https://github.com/pydata/pandas/pull/4659


Resolving patch:
diff --git a/pandas/core/series.py b/pandas/core/series.py
--- a/pandas/core/series.py
+++ b/pandas/core/series.py
@@ -1152,18 +1152,21 @@ def repeat(self, reps):
         new_values = self.values.repeat(reps)
         return self._constructor(new_values, index=new_index, name=self.name)
 
-    def reshape(self, newshape, order='C'):
+    def reshape(self, *args, **kwargs):
         """
         See numpy.ndarray.reshape
         """
-        if order not in ['C', 'F']:
-            raise TypeError(
-                "must specify a tuple / singular length to reshape")
-
-        if isinstance(newshape, tuple) and len(newshape) > 1:
-            return self.values.reshape(newshape, order=order)
+        if len(args) == 1 and hasattr(args[0], '__iter__'):
+            shape = args[0]
         else:
-            return ndarray.reshape(self, newshape, order)
+            shape = args
+
+        if tuple(shape) == self.shape:
+            # XXX ignoring the "order" keyword.
+            return self
+
+        return self.values.reshape(shape, **kwargs)
+
 
     def get(self, label, default=None):
         """


Test patch:
diff --git a/pandas/tests/test_series.py b/pandas/tests/test_series.py
--- a/pandas/tests/test_series.py
+++ b/pandas/tests/test_series.py
@@ -1046,12 +1046,16 @@ def test_basic_getitem_setitem_corner(self):
                           [5, slice(None, None)], 2)
 
     def test_reshape_non_2d(self):
+        # GH 4554
         x = Series(np.random.random(201), name='x')
-        self.assertRaises(TypeError, x.reshape, (len(x),))
+        self.assertTrue(x.reshape(x.shape,) is x)
 
         # GH 2719
         a = Series([1, 2, 3, 4])
-        self.assertRaises(TypeError, a.reshape, 2, 2)
+        result = a.reshape(2, 2)
+        expected = a.values.reshape(2, 2)
+        np.testing.assert_array_equal(result, expected)
+        self.assertTrue(type(result) is type(expected))
 
     def test_reshape_2d_return_array(self):
         x = Series(np.random.random(201), name='x')