Repository: pandas-dev/pandas

Issue:
Changing columns with `+=` gives UnboundLocalError
```
In [1]: import numpy as np
In [2]: import pandas as pd
In [3]: np.random.seed(10)
In [4]: a = np.random.randint(0, 20, (6, 5))
In [5]: df = pd.DataFrame(a, columns=list('abcde'))
In [6]: df
Out[6]:
    a   b   c   d   e
0   9   4  15   0  17
1  16  17   8   9   0
2  10   8   4  19  16
3   4  15  11  11   1
4   8   4  14  17  19
5  13   5  13  19  13
```

Changing columns with `+` is fine

```
In [7]: df.columns = df.columns + '_x'
In [8]: df
Out[8]:
   a_x  b_x  c_x  d_x  e_x
0    9    4   15    0   17
1   16   17    8    9    0
2   10    8    4   19   16
3    4   15   11   11    1
4    8    4   14   17   19
5   13    5   13   19   13
```

The `+=` operator on the other hand correctly changes the columns,

```
In [9]: df.columns += '_y'
In [10]: df.columns
Out[10]: Index([u'a_x_y', u'b_x_y', u'c_x_y', u'd_x_y', u'e_x_y'], dtype=object)
```

but gives an error when trying to display the whole dataframe:

```
In [11]: df
Out[11]: ---------------------------------------------------------------------------
UnboundLocalError                         Traceback (most recent call last)
```

Traceback is [here](https://gist.github.com/d10genes/6716510). Not sure if it's an ipython or pandas issue. `pd.__version__ == '0.12.0-371-g1434776'`

Changing columns with `+=` gives UnboundLocalError
```
In [1]: import numpy as np
In [2]: import pandas as pd
In [3]: np.random.seed(10)
In [4]: a = np.random.randint(0, 20, (6, 5))
In [5]: df = pd.DataFrame(a, columns=list('abcde'))
In [6]: df
Out[6]:
    a   b   c   d   e
0   9   4  15   0  17
1  16  17   8   9   0
2  10   8   4  19  16
3   4  15  11  11   1
4   8   4  14  17  19
5  13   5  13  19  13
```

Changing columns with `+` is fine

```
In [7]: df.columns = df.columns + '_x'
In [8]: df
Out[8]:
   a_x  b_x  c_x  d_x  e_x
0    9    4   15    0   17
1   16   17    8    9    0
2   10    8    4   19   16
3    4   15   11   11    1
4    8    4   14   17   19
5   13    5   13   19   13
```

The `+=` operator on the other hand correctly changes the columns,

```
In [9]: df.columns += '_y'
In [10]: df.columns
Out[10]: Index([u'a_x_y', u'b_x_y', u'c_x_y', u'd_x_y', u'e_x_y'], dtype=object)
```

but gives an error when trying to display the whole dataframe:

```
In [11]: df
Out[11]: ---------------------------------------------------------------------------
UnboundLocalError                         Traceback (most recent call last)
```

Traceback is [here](https://gist.github.com/d10genes/6716510). Not sure if it's an ipython or pandas issue. `pd.__version__ == '0.12.0-371-g1434776'`



Discussion:
this is a trivial fix, just define `__iadd__ = __add__` in `core/index.py`

need a test, and I think it makes sense to disable methods that don't make sense on an index

`mul,trudev,floordiv,pow`
`imul,itruediv,iflloordiv,ipow`

disabling is easy (just set them like in`core/base.py/FrozenNDArray` )

do a PR?

> do a PR?

I'd love to, but I'll probably have to wait till after work tomorrow if there's no rush.

no problem...

this is a trivial fix, just define `__iadd__ = __add__` in `core/index.py`

need a test, and I think it makes sense to disable methods that don't make sense on an index

`mul,trudev,floordiv,pow`
`imul,itruediv,iflloordiv,ipow`

disabling is easy (just set them like in`core/base.py/FrozenNDArray` )

do a PR?

> do a PR?

I'd love to, but I'll probably have to wait till after work tomorrow if there's no rush.

no problem...


Resolving patch:
diff --git a/pandas/core/index.py b/pandas/core/index.py
--- a/pandas/core/index.py
+++ b/pandas/core/index.py
@@ -832,6 +832,7 @@ def __add__(self, other):
         else:
             return Index(self.view(np.ndarray) + other)
 
+    __iadd__ = __add__
     __eq__ = _indexOp('__eq__')
     __ne__ = _indexOp('__ne__')
     __lt__ = _indexOp('__lt__')


Test patch:
diff --git a/pandas/tests/test_index.py b/pandas/tests/test_index.py
--- a/pandas/tests/test_index.py
+++ b/pandas/tests/test_index.py
@@ -382,6 +382,14 @@ def test_add_string(self):
         self.assert_('a' not in index2)
         self.assert_('afoo' in index2)
 
+    def test_iadd_string(self):
+        index = pd.Index(['a', 'b', 'c'])
+        # doesn't fail test unless there is a check before `+=`
+        self.assert_('a' in index)
+
+        index += '_x'
+        self.assert_('a_x' in index)
+
     def test_diff(self):
         first = self.strIndex[5:20]
         second = self.strIndex[:10]