Repository: scipy/scipy

Issue:
BUG: Slices of sparse matrices return incorrect dtype
Sparse matrices, when sliced, will return a new matrix of the default dtype rather than the same dtype as initialized.

This is true of lil_matrix:

```
>>> a = scipy.sparse.lil_matrix((1, 100), dtype="string")
>>> a
<1x100 sparse matrix of type '<type 'numpy.string_'>'
    with 0 stored elements in LInked List format>
>>> a[0, 10:20]
<1x10 sparse matrix of type '<type 'numpy.int64'>'
    with 0 stored elements in LInked List format>
```

And of dok_matrix:

```
>>> a = scipy.sparse.dok_matrix((1, 100), dtype="string")
>>> a
<1x100 sparse matrix of type '<type 'numpy.string_'>'
    with 0 stored elements in Dictionary Of Keys format>
>>> a[0, 10:20]
<1x10 sparse matrix of type '<type 'numpy.float64'>'
    with 0 stored elements in Dictionary Of Keys format>
```



Discussion:

Resolving patch:
diff --git a/scipy/sparse/dok.py b/scipy/sparse/dok.py
--- a/scipy/sparse/dok.py
+++ b/scipy/sparse/dok.py
@@ -179,7 +179,7 @@ def __getitem__(self, key):
                                  or last >= self.shape[0]:
                         raise IndexError('index out of bounds')
                     newshape = (last-first+1, 1)
-                    new = dok_matrix(newshape)
+                    new = dok_matrix(newshape, dtype=self.dtype)
                     # ** This uses linear time in the size m of dimension 0:
                     # new[0:seq[-1]-seq[0]+1, 0] = \
                     #         [self.get((element, j), 0) for element in seq]
@@ -214,7 +214,7 @@ def __getitem__(self, key):
                          or last >= self.shape[1]:
                 raise IndexError("index out of bounds")
             newshape = (1, last-first+1)
-            new = dok_matrix(newshape)
+            new = dok_matrix(newshape, dtype=self.dtype)
             # ** This uses linear time in the size n of dimension 1:
             # new[0, 0:seq[-1]-seq[0]+1] = \
             #         [self.get((i, element), 0) for element in seq]
diff --git a/scipy/sparse/lil.py b/scipy/sparse/lil.py
--- a/scipy/sparse/lil.py
+++ b/scipy/sparse/lil.py
@@ -242,7 +242,7 @@ def __getitem__(self, index):
 
         return self.__class__([[self._get1(iii, jjj) for iii, jjj in
                                 zip(ii, jj)] for ii, jj in
-                               zip(i.tolist(), j.tolist())])
+                               zip(i.tolist(), j.tolist())], dtype=self.dtype)
 
     def _insertat2(self, row, data, j, x):
         """ helper for __setitem__: insert a value in the given row/data at


Test patch:
diff --git a/scipy/sparse/tests/test_base.py b/scipy/sparse/tests/test_base.py
--- a/scipy/sparse/tests/test_base.py
+++ b/scipy/sparse/tests/test_base.py
@@ -1691,6 +1691,11 @@ def test_solve(self):
 
 
 class _TestSlicing:
+    def test_dtype_preservation(self):
+        assert_equal(self.spmatrix((1,10), dtype=np.int16)[0,1:5].dtype, np.int16)
+        assert_equal(self.spmatrix((1,10), dtype=np.int32)[0,1:5].dtype, np.int32)
+        assert_equal(self.spmatrix((1,10), dtype=np.float32)[0,1:5].dtype, np.float32)
+        assert_equal(self.spmatrix((1,10), dtype=np.float64)[0,1:5].dtype, np.float64)
     def test_get_horiz_slice(self):
         B = asmatrix(arange(50.).reshape(5,10))
         A = self.spmatrix(B)