Repository: pydata/sparse

Issue:
COO constructor accepts 2D data with shape (n, 1) which breaks other things
COO constructor accepts effectively 1 dimensional data in a 2D container with with shape (n, 1), but this causes breakage later e.g. todense raises

`ValueError: shape mismatch: value array of shape (<n>,1) could not be broadcast to indexing result of shape (<n>,)` 

**To Reproduce**
```python
coords = np.array([[1,1,4], [4,7,8]])
data = np.expand_dims(np.arange(3), 1)

d = sparse.COO(coords, data=data,shape=(10,10)) # <= works
d.todense() # <= fails
```

**Expected behavior**
COO constructor should validate input to reject data that won't work later. Maybe it could apply squeeze() as a convenience.

**System**
 - OS and version: Ubuntu 18.04
 - `sparse` version '0.10.0'
 - NumPy version '1.19.0'
 - Numba version '0.50.1'


Discussion:
codecov[bot]: # [Codecov](https://codecov.io/gh/pydata/sparse/pull/386?src=pr&el=h1) Report
> Merging [#386](https://codecov.io/gh/pydata/sparse/pull/386?src=pr&el=desc) into [master](https://codecov.io/gh/pydata/sparse/commit/f4a2435269b63bbb36c2fd5c5af785251360a13d&el=desc) will **decrease** coverage by `0.01%`.
> The diff coverage is `100.00%`.


```diff
@@            Coverage Diff             @@
##           master     #386      +/-   ##
==========================================
- Coverage   94.17%   94.16%   -0.02%     
==========================================
  Files          19       19              
  Lines        2437     2586     +149     
==========================================
+ Hits         2295     2435     +140     
- Misses        142      151       +9     
```




Patch:
diff --git a/sparse/_coo/core.py b/sparse/_coo/core.py
index 0f6c661..3d5b306 100644
--- a/sparse/_coo/core.py
+++ b/sparse/_coo/core.py
@@ -230,6 +230,9 @@ class COO(SparseArray, NDArrayOperatorsMixin):  # lgtm [py/missing-equals]
         if self.data.ndim == 0:
             self.data = np.broadcast_to(self.data, self.coords.shape[1])
 
+        if self.data.ndim != 1:
+            raise ValueError("data must be a scalar or 1-dimensional.")
+
         if shape and not self.coords.size:
             self.coords = np.zeros(
                 (len(shape) if isinstance(shape, Iterable) else 1, 0), dtype=np.uint64


Test patch:
diff --git a/sparse/tests/test_coo.py b/sparse/tests/test_coo.py
index 3acc3a4..4c22f81 100644
--- a/sparse/tests/test_coo.py
+++ b/sparse/tests/test_coo.py
@@ -2369,3 +2369,9 @@ def test_scalar_list_init():
 
     assert a.todense() == 0
     assert b.todense() == 1
+
+
+def test_raise_on_nd_data():
+    s1 = sparse.random((2, 3, 4), density=0.5)
+    with pytest.raises(ValueError):
+        sparse.COO(s1.coords, s1.data[:, None], shape=(2, 3, 4))