Repository: pandas-dev/pandas
Pull request: TST: Test Loc to set Multiple Items to multiple new columns
- [x] closes #25594
- [x] tests added / passed
- [x] Ensure all linting tests pass, see [here](https://pandas.pydata.org/pandas-docs/dev/development/contributing.html#code-standards) for how to run them
- [x] whatsnew entry
added test to pandas/tests/indexing/multi/test_loc.py

Problem statement:
Adding multiple columns with loc fails
#### Code Sample, a copy-pastable example if possible

```python
import pandas as pd

df = pd.DataFrame(index=[1, 2], columns = list('ab'))

# Single assignment on existing column
df.loc[1, 'a'] = 1

# Multiple assignment on existing column
df.loc[2, ['a', 'b']] = [1, 2]

# Single assignment on new column
df.loc[3, 'c'] = 3

# Multiple assignment on single new column
df.loc[[1, 2], 'l'] = [6, 7]

# Multiple assignment on multiple new column
# Surprisingly fails
try:
    df.loc[3, ['d', 'e']] = [6, 7]
    print(df)
except KeyError:
    print("Error")

```
#### Problem description
The behaviour of loc is surprising:
- When assigning, new columns and index are created as required.
- You can assign multiple index and columns
- BUT, if you try to create a column or index while doing multiple assignment, new columns and index are NOT created as required, and you get a KeyError.

Futhermore, using the indexing operators `[]` directly will create the required columns.

#### Expected Output
```
     a    b    c    l    d    e
1    1  NaN  NaN  6.0  NaN  NaN
2    1    2  NaN  7.0  NaN  NaN
3  NaN  NaN  3.0  NaN  6.0  7.0
```
#### Output of ``pd.show_versions()``

<details>

INSTALLED VERSIONS
------------------
commit: None
python: 3.7.2.final.0
python-bits: 64
OS: Darwin
OS-release: 18.2.0
machine: x86_64
processor: i386
byteorder: little
LC_ALL: en_US.UTF-8
LANG: en_US.UTF-8
LOCALE: en_US.UTF-8

pandas: 0.24.1
pytest: 4.2.0
pip: 19.0.2
setuptools: 40.8.0
Cython: 0.28.5
numpy: 1.15.2
scipy: 1.2.0
pyarrow: None
xarray: None
IPython: 7.0.1
sphinx: 1.8.1
patsy: None
dateutil: 2.7.3
pytz: 2018.5
blosc: None
bottleneck: None
tables: None
numexpr: None
feather: None
matplotlib: 3.0.2
openpyxl: None
xlrd: None
xlwt: None
xlsxwriter: None
lxml.etree: 4.2.5
bs4: None
html5lib: 1.0.1
sqlalchemy: None
pymysql: None
psycopg2: None
jinja2: 2.10
s3fs: None
fastparquet: None
pandas_gbq: None
pandas_datareader: None
gcsfs: None

</details>

Hints from issue discussion:
Thanks. You might need to look into `_convert_indexer` in pandas/core/indexing.py to check why `is_setter` implies `raise_missing`. It seems like this should work but I may be missing something.

For clarity, could you edit down your issue to include just the

```
df = ...
df.loc[3, ['d', 'e']] = [6, 7]
```

and your expected output?
This looks to work on master now. Could use a test

```
In [11]: import pandas as pd
    ...:
    ...: df = pd.DataFrame(index=[1, 2], columns = list('ab'))
    ...:
    ...: # Single assignment on existing column
    ...: df.loc[1, 'a'] = 1
    ...:
    ...: # Multiple assignment on existing column
    ...: df.loc[2, ['a', 'b']] = [1, 2]
    ...:
    ...: # Single assignment on new column
    ...: df.loc[3, 'c'] = 3
    ...:
    ...: # Multiple assignment on single new column
    ...: df.loc[[1, 2], 'l'] = [6, 7]
    ...:
    ...: # Multiple assignment on multiple new column
    ...: # Surprisingly fails
    ...: try:
    ...:     df.loc[3, ['d', 'e']] = [6, 7]
    ...:     print(df)
    ...: except KeyError:
    ...:     print("Error")
    ...:
     a    b    c    l    d    e
1    1  NaN  NaN  6.0  NaN  NaN
2    1    2  NaN  7.0  NaN  NaN
3  NaN  NaN  3.0  NaN  6.0  7.0
```

Commit message: Test Loc to set Multiple Items to multiple new columns - Changes Made

Patch to review:
diff --git a/pandas/tests/indexing/test_loc.py b/pandas/tests/indexing/test_loc.py
index 6de83e34122c2..2a33d7b658ab4 100644
--- a/pandas/tests/indexing/test_loc.py
+++ b/pandas/tests/indexing/test_loc.py
@@ -2768,3 +2768,12 @@ def test_loc_setitem_dict_timedelta_multiple_set(self):
             [[Timedelta(6, unit="s"), "foo"]], columns=["time", "value"], index=[1]
         )
         tm.assert_frame_equal(result, expected)
+
+    def test_loc_set_multiple_items_in_multiple_new_columns(self):
+        # GH 25594
+        df = DataFrame(index=[1, 2], columns=["a"])
+        df.loc[1, ["b", "c"]] = [6, 7]
+
+        expected = DataFrame({"a": [np.nan, np.nan], "b": [6, np.nan], "c": [7, np.nan]}, index = [1, 2])
+
+        tm.assert_frame_equal(df, expected, check_dtype=False)


Code review comments:
diff_hunk: @@ -2773,10 +2773,7 @@ def test_loc_set_multiple_items_in_multiple_new_columns(self):
         # GH 25594
         df = DataFrame(index=[1, 2], columns=["a"])
         df.loc[1, ["b", "c"]] = [6, 7]
-        result = df.copy()
 
-        expected = DataFrame(index=[1, 2], columns=["a", "b", "c"])
-        expected.loc[1, "b"] = 6
-        expected.loc[1, "c"] = 7
+        expected = DataFrame({"a": [np.nan, np.nan], "b": [6, np.nan], "c": [7, np.nan]}, index = [1, 2])
 
-        tm.assert_frame_equal(result, expected, check_dtype=False)
+        tm.assert_frame_equal(df, expected, check_dtype=False)
path: pandas/tests/indexing/test_loc.py
text: @user1:
Please remove the check_dtype=False parameter

@author:
@user1 I tried the remove the "check_dtype=False" parameter put the test is not passing. This is the error I'm getting: "- AssertionError: Attributes of DataFrame.iloc[:, 0] (column name="a") are different". I think the dtype of df and expected are different

@user1:
Then you have to define expected accordingly