Repository: pandas-dev/pandas

Issue:
BUG: test_interp_regression failure
```
test_interp_regression (__main__.TestSeries) ... > /home/dsm/sys/pandas/pandas/tests/stringsource(327)View.MemoryView.memoryview.__cinit__ (scipy/interpolate/_ppoly.c:19922)()
(Pdb) cont
ERROR

======================================================================
ERROR: test_interp_regression (__main__.TestSeries)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test_generic.py", line 501, in test_interp_regression
    interp_s = ser.reindex(new_index).interpolate(method='pchip')
  File "/usr/local/lib/python2.7/dist-packages/pandas-0.14.0_12_g150cb3b-py2.7-linux-i686.egg/pandas/core/generic.py", line 2582, in interpolate
    **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/pandas-0.14.0_12_g150cb3b-py2.7-linux-i686.egg/pandas/core/internals.py", line 2197, in interpolate
    return self.apply('interpolate', **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/pandas-0.14.0_12_g150cb3b-py2.7-linux-i686.egg/pandas/core/internals.py", line 2164, in apply
    applied = getattr(b, f)(**kwargs)
  File "/usr/local/lib/python2.7/dist-packages/pandas-0.14.0_12_g150cb3b-py2.7-linux-i686.egg/pandas/core/internals.py", line 667, in interpolate
    **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/pandas-0.14.0_12_g150cb3b-py2.7-linux-i686.egg/pandas/core/internals.py", line 733, in _interpolate
    interp_values = np.apply_along_axis(func, axis, data)
  File "/usr/local/lib/python2.7/dist-packages/numpy/lib/shape_base.py", line 81, in apply_along_axis
    res = func1d(arr[tuple(i.tolist())],*args)
  File "/usr/local/lib/python2.7/dist-packages/pandas-0.14.0_12_g150cb3b-py2.7-linux-i686.egg/pandas/core/internals.py", line 730, in func
    bounds_error=False, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/pandas-0.14.0_12_g150cb3b-py2.7-linux-i686.egg/pandas/core/common.py", line 1489, in interpolate_1d
    bounds_error=bounds_error, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/pandas-0.14.0_12_g150cb3b-py2.7-linux-i686.egg/pandas/core/common.py", line 1541, in _interpolate_scipy_wrapper
    new_y = method(x, y, new_x)
  File "/usr/local/lib/python2.7/dist-packages/scipy/interpolate/_monotone.py", line 221, in pchip_interpolate
    return P(x)
  File "/usr/local/lib/python2.7/dist-packages/scipy/interpolate/_monotone.py", line 98, in __call__
    out = self._bpoly(x, der, extrapolate)
  File "/usr/local/lib/python2.7/dist-packages/scipy/interpolate/interpolate.py", line 689, in __call__
    self._evaluate(x, nu, extrapolate, out)
  File "/usr/local/lib/python2.7/dist-packages/scipy/interpolate/interpolate.py", line 1087, in _evaluate
    self.x, x, nu, bool(extrapolate), out, self.c.dtype)
  File "_ppoly.pyx", line 846, in scipy.interpolate._ppoly.evaluate_bernstein (scipy/interpolate/_ppoly.c:15014)
  File "stringsource", line 622, in View.MemoryView.memoryview_cwrapper (scipy/interpolate/_ppoly.c:23370)
  File "stringsource", line 327, in View.MemoryView.memoryview.__cinit__ (scipy/interpolate/_ppoly.c:19922)
ValueError: buffer source array is read-only

----------------------------------------------------------------------
Ran 63 tests in 3.981s

FAILED (SKIP=1, errors=1)
```

Version info:

```
>>> pd.show_versions()

INSTALLED VERSIONS
------------------
commit: None
python: 2.7.5.final.0
python-bits: 32
OS: Linux
OS-release: 3.11.0-20-generic
machine: i686
processor: i686
byteorder: little
LC_ALL: None
LANG: en_CA.UTF-8

pandas: 0.14.0-12-g150cb3b
nose: 1.3.1
Cython: 0.20.1
numpy: 1.9.0.dev-ef7901d
scipy: 0.15.0.dev-93656a8
statsmodels: 0.6.0.dev-985037f
IPython: 2.0.0-dev
sphinx: 1.2.2
patsy: 0.2.1
scikits.timeseries: None
dateutil: 2.2
pytz: 2014.1
bottleneck: 0.8.0
tables: None
numexpr: 2.3.1
matplotlib: 1.4.x
openpyxl: 2.0.2
xlrd: 0.9.3
xlwt: 0.7.5
xlsxwriter: 0.5.5
lxml: 3.3.3
bs4: 4.3.2
html5lib: 1.0b3
bq: None
apiclient: 1.2
rpy2: None
sqlalchemy: 0.9.3
pymysql: None
psycopg2: None
```



Discussion:
excellent 32-bit scipy testing !

can u try putting a copy before it's passed into interpolate (insert right before the scipy call)
maybe some kind of view corruption

Adding

```
        x = x.copy()
        y = y.copy()
        new_x = new_x.copy()
```

to common.py/interpolate_1d on the alt_methods path seems to prevent the problem.  Coping only one of the arrays doesn't seem to.

After some experiments, `y` doesn't seem to need to be copied, only `x` and `new_x`.   That makes a little sense, anyway, as right before the copies we have

```
x.flags:
  C_CONTIGUOUS : True
  F_CONTIGUOUS : True
  OWNDATA : False
  WRITEABLE : False
  ALIGNED : True
  UPDATEIFCOPY : False
y.flags:
  C_CONTIGUOUS : True
  F_CONTIGUOUS : True
  OWNDATA : True
  WRITEABLE : True
  ALIGNED : True
  UPDATEIFCOPY : False
new_x.flags:
  C_CONTIGUOUS : True
  F_CONTIGUOUS : True
  OWNDATA : False
  WRITEABLE : False
  ALIGNED : True
  UPDATEIFCOPY : False
```

but I admit I don't immediately see why `x` should need to be copied.

cc @TomAugspurger 

probably the interpolation routines do some in-place work on these arrays. prob a bug on scipy side in that they should either explicity copy if they are messing with it, or provide documentation of the lack of guarantees. care to file an upstream bug as well?

PR to take care of this (I guess need to explicity copy) if its a view.

@dsm054 can you do a PR for this?

Sure, will do.


Resolving patch:
diff --git a/pandas/core/common.py b/pandas/core/common.py
--- a/pandas/core/common.py
+++ b/pandas/core/common.py
@@ -1538,6 +1538,14 @@ def _interpolate_scipy_wrapper(x, y, new_x, method, fill_value=None,
         terp = interpolate.UnivariateSpline(x, y, k=order)
         new_y = terp(new_x)
     else:
+        # GH 7295: need to be able to write for some reason
+        # in some circumstances: check all three
+        if not x.flags.writeable:
+            x = x.copy()
+        if not y.flags.writeable:
+            y = y.copy()
+        if not new_x.flags.writeable:
+            new_x = new_x.copy()
         method = alt_methods[method]
         new_y = method(x, y, new_x)
     return new_y


Test patch: