Repository: pandas-dev/pandas

Issue:
BUG: unexpected assign by a single-element list
#### Code Sample, a copy-pastable example if possible

```python
import pandas as pd
df = pd.DataFrame([[1,2,3], [4,5,6]],columns=["A", "B", "C"])
df.loc[0, ["C"]] = ["Z"]
df
   A  B    C
0  1  2  [Z]
1  4  5    6
```
#### Problem description
This issue is derived from [https://stackoverflow.com/questions/48195993/unexpectedly-assign-in-pandas-by-df-loc-and-single-element-list](https://stackoverflow.com/questions/48195993/unexpectedly-assign-in-pandas-by-df-loc-and-single-element-list)

At first I thought this happened because the method is not idiomatic. But I noticed a method with numpy.array is showed in [here](http://pandas.pydata.org/pandas-docs/stable/10min.html) (section:Setting)
`df.loc[:,'D'] = np.array([5] * len(df))`
So I reported this  just in case. Sorry but I cannot judge whether my method is completely non-idiomatic 
or whether latest reported bugs contains mine.  
#### Expected Output
```
df
   A  B  C
0  1  2  Z
1  4  5  6
```

#### Some trials and errors

<details>

```
#more elements : as I expected
df = pd.DataFrame([[1,2,3],[4,5,6]], columns=["A", "B", "C"])
df.loc[0, ["A", "B"]] = ["X", "Y"]
df
   A  B  C
0  X  Y  3
1  4  5  6

#axis=0 : as I expected
df = pd.DataFrame([[1,2,3],[4,5,6]], columns=["A", "B", "C"])
df.loc[[0], "C"] = ["Z"]
df
   A  B  C
0  1  2  Z
1  4  5  6

#using numpy.array : NOT as I expected
import numpy as np
df = pd.DataFrame([[1,2,3],[4,5,6]], columns=["A", "B", "C"])
s = np.array(["Z"])
df.loc[0, ["C"]] = s
df
   A  B    C
0  1  2  [Z]
1  4  5    6

#assign instead a list containing int : as I expected
df = pd.DataFrame([[1,2,3], [4,5,6]],columns=["A", "B", "C"])
df.loc[0, ["C"]] = [9]
df
   A  B  C
0  1  2  9
1  4  5  6
```

</details>

#### Output of ``pd.show_versions()`` 

<details>

INSTALLED VERSIONS
------------------
commit: None
python: 3.6.3.final.0
python-bits: 64
OS: Windows
OS-release: 7
machine: AMD64
processor: Intel64 Family 6 Model 60 Stepping 3, GenuineIntel
byteorder: little
LC_ALL: None
LANG: None
LOCALE: None.None

pandas: 0.22.0
pytest: None
pip: 9.0.1
setuptools: 38.2.5
Cython: None
numpy: 1.14.0
scipy: 1.0.0
pyarrow: None
xarray: None
IPython: None
sphinx: None
patsy: None
dateutil: 2.6.1
pytz: 2017.3
blosc: None
bottleneck: None
tables: None
numexpr: None
feather: None
matplotlib: 2.1.1
openpyxl: None
xlrd: None
xlwt: None
xlsxwriter: None
lxml: None
bs4: 4.6.0
html5lib: None
sqlalchemy: None
pymysql: None
psycopg2: None
jinja2: None
s3fs: None
fastparquet: None
pandas_gbq: None
pandas_datareader: None

</details>



Discussion:
yeah I think this should infer this list-like asd you are assigning to a Series (because of the list for the columns). a pull-request or deeper investigation would be great.

Resolving patch:
diff --git a/pandas/core/indexing.py b/pandas/core/indexing.py
--- a/pandas/core/indexing.py
+++ b/pandas/core/indexing.py
@@ -532,7 +532,8 @@ def setter(item, v):
 
             def can_do_equal_len():
                 """ return True if we have an equal len settable """
-                if not len(labels) == 1 or not np.iterable(value):
+                if (not len(labels) == 1 or not np.iterable(value) or
+                        is_scalar(plane_indexer[0])):
                     return False
 
                 l = len(value)


Test patch:
diff --git a/pandas/tests/indexing/test_iloc.py b/pandas/tests/indexing/test_iloc.py
--- a/pandas/tests/indexing/test_iloc.py
+++ b/pandas/tests/indexing/test_iloc.py
@@ -10,6 +10,7 @@
 from pandas import Series, DataFrame, date_range, concat, isna
 from pandas.util import testing as tm
 from pandas.tests.indexing.common import Base
+from pandas.api.types import is_scalar
 
 
 class TestiLoc(Base):
@@ -526,6 +527,21 @@ def test_iloc_setitem_list_of_lists(self):
                                   B=[5, 6, 11, 13, 9]))
         tm.assert_frame_equal(df, expected)
 
+    @pytest.mark.parametrize(
+        'indexer', [[0], slice(None, 1, None), np.array([0])])
+    @pytest.mark.parametrize(
+        'value', [['Z'], np.array(['Z'])])
+    def test_iloc_setitem_with_scalar_index(self, indexer, value):
+        # GH #19474
+        # assigning like "df.iloc[0, [0]] = ['Z']" should be evaluated
+        # elementwisely, not using "setter('A', ['Z'])".
+
+        df = pd.DataFrame([[1, 2], [3, 4]], columns=['A', 'B'])
+        df.iloc[0, indexer] = value
+        result = df.iloc[0, 0]
+
+        assert is_scalar(result) and result == 'Z'
+
     def test_iloc_mask(self):
 
         # GH 3631, iloc with a mask (of a series) should raise
diff --git a/pandas/tests/indexing/test_loc.py b/pandas/tests/indexing/test_loc.py
--- a/pandas/tests/indexing/test_loc.py
+++ b/pandas/tests/indexing/test_loc.py
@@ -11,6 +11,7 @@
 from pandas import Series, DataFrame, Timestamp, date_range, MultiIndex, Index
 from pandas.util import testing as tm
 from pandas.tests.indexing.common import Base
+from pandas.api.types import is_scalar
 
 
 class TestLoc(Base):
@@ -555,6 +556,21 @@ def test_loc_setitem_frame_multiples(self):
         df.loc[2:4] = rhs
         tm.assert_frame_equal(df, expected)
 
+    @pytest.mark.parametrize(
+        'indexer', [['A'], slice(None, 'A', None), np.array(['A'])])
+    @pytest.mark.parametrize(
+        'value', [['Z'], np.array(['Z'])])
+    def test_loc_setitem_with_scalar_index(self, indexer, value):
+        # GH #19474
+        # assigning like "df.loc[0, ['A']] = ['Z']" should be evaluated
+        # elementwisely, not using "setter('A', ['Z'])".
+
+        df = pd.DataFrame([[1, 2], [3, 4]], columns=['A', 'B'])
+        df.loc[0, indexer] = value
+        result = df.loc[0, 'A']
+
+        assert is_scalar(result) and result == 'Z'
+
     def test_loc_coerceion(self):
 
         # 12411