Skip to content

Commit 499eb21

Browse files
committed
Merge pull request pandas-dev#10428 from jreback/indexing
BUG: using .loc[:,column] fails type coercion when the object is a multi-index
2 parents 512d9d5 + 9e517ac commit 499eb21

File tree

3 files changed

+33
-9
lines changed

3 files changed

+33
-9
lines changed

pandas/core/common.py

+5
Original file line numberDiff line numberDiff line change
@@ -2605,9 +2605,14 @@ def is_list_like(arg):
26052605
not isinstance(arg, compat.string_and_binary_types))
26062606

26072607
def is_null_slice(obj):
2608+
""" we have a null slice """
26082609
return (isinstance(obj, slice) and obj.start is None and
26092610
obj.stop is None and obj.step is None)
26102611

2612+
def is_full_slice(obj, l):
2613+
""" we have a full length slice """
2614+
return (isinstance(obj, slice) and obj.start == 0 and
2615+
obj.stop == l and obj.step is None)
26112616

26122617
def is_hashable(arg):
26132618
"""Return True if hash(arg) will succeed, False otherwise.

pandas/core/indexing.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import pandas.core.common as com
77
from pandas.core.common import (is_bool_indexer, is_integer_dtype,
88
_asarray_tuplesafe, is_list_like, isnull,
9-
is_null_slice,
9+
is_null_slice, is_full_slice,
1010
ABCSeries, ABCDataFrame, ABCPanel, is_float,
1111
_values_from_object, _infer_fill_value, is_integer)
1212
import numpy as np
@@ -399,10 +399,10 @@ def setter(item, v):
399399
pi = plane_indexer[0] if lplane_indexer == 1 else plane_indexer
400400

401401
# perform the equivalent of a setitem on the info axis
402-
# as we have a null slice which means essentially reassign to the columns
403-
# of a multi-dim object
404-
# GH6149
405-
if isinstance(pi, tuple) and all(is_null_slice(idx) for idx in pi):
402+
# as we have a null slice or a slice with full bounds
403+
# which means essentially reassign to the columns of a multi-dim object
404+
# GH6149 (null slice), GH10408 (full bounds)
405+
if isinstance(pi, tuple) and all(is_null_slice(idx) or is_full_slice(idx, len(self.obj)) for idx in pi):
406406
s = v
407407
else:
408408
# set the item, possibly having a dtype change

pandas/tests/test_indexing.py

+23-4
Original file line numberDiff line numberDiff line change
@@ -1072,6 +1072,25 @@ def test_loc_setitem_consistency(self):
10721072
df['x'] = 1
10731073
assert_frame_equal(df,expected)
10741074

1075+
# .loc[:,column] setting with slice == len of the column
1076+
# GH10408
1077+
data = """Level_0,,,Respondent,Respondent,Respondent,OtherCat,OtherCat
1078+
Level_1,,,Something,StartDate,EndDate,Yes/No,SomethingElse
1079+
Region,Site,RespondentID,,,,,
1080+
Region_1,Site_1,3987227376,A,5/25/2015 10:59,5/25/2015 11:22,Yes,
1081+
Region_1,Site_1,3980680971,A,5/21/2015 9:40,5/21/2015 9:52,Yes,Yes
1082+
Region_1,Site_2,3977723249,A,5/20/2015 8:27,5/20/2015 8:41,Yes,
1083+
Region_1,Site_2,3977723089,A,5/20/2015 8:33,5/20/2015 9:09,Yes,No"""
1084+
1085+
df = pd.read_csv(StringIO(data),header=[0,1], index_col=[0,1,2])
1086+
df.loc[:,('Respondent','StartDate')] = pd.to_datetime(df.loc[:,('Respondent','StartDate')])
1087+
df.loc[:,('Respondent','EndDate')] = pd.to_datetime(df.loc[:,('Respondent','EndDate')])
1088+
df.loc[:,('Respondent','Duration')] = df.loc[:,('Respondent','EndDate')] - df.loc[:,('Respondent','StartDate')]
1089+
1090+
df.loc[:,('Respondent','Duration')] = df.loc[:,('Respondent','Duration')].astype('timedelta64[s]')
1091+
expected = Series([1380,720,840,2160.],index=df.index,name=('Respondent','Duration'))
1092+
assert_series_equal(df[('Respondent','Duration')],expected)
1093+
10751094
def test_loc_setitem_frame(self):
10761095
df = self.frame_labels
10771096

@@ -2331,27 +2350,27 @@ def test_setitem_dtype_upcast(self):
23312350
assert_frame_equal(df,expected)
23322351

23332352
# GH10280
2334-
df = DataFrame(np.arange(6,dtype='int64').reshape(2, 3),
2353+
df = DataFrame(np.arange(6,dtype='int64').reshape(2, 3),
23352354
index=list('ab'),
23362355
columns=['foo', 'bar', 'baz'])
23372356

23382357
for val in [3.14, 'wxyz']:
23392358
left = df.copy()
23402359
left.loc['a', 'bar'] = val
2341-
right = DataFrame([[0, val, 2], [3, 4, 5]],
2360+
right = DataFrame([[0, val, 2], [3, 4, 5]],
23422361
index=list('ab'),
23432362
columns=['foo', 'bar', 'baz'])
23442363

23452364
assert_frame_equal(left, right)
23462365
self.assertTrue(com.is_integer_dtype(left['foo']))
23472366
self.assertTrue(com.is_integer_dtype(left['baz']))
23482367

2349-
left = DataFrame(np.arange(6,dtype='int64').reshape(2, 3) / 10.0,
2368+
left = DataFrame(np.arange(6,dtype='int64').reshape(2, 3) / 10.0,
23502369
index=list('ab'),
23512370
columns=['foo', 'bar', 'baz'])
23522371
left.loc['a', 'bar'] = 'wxyz'
23532372

2354-
right = DataFrame([[0, 'wxyz', .2], [.3, .4, .5]],
2373+
right = DataFrame([[0, 'wxyz', .2], [.3, .4, .5]],
23552374
index=list('ab'),
23562375
columns=['foo', 'bar', 'baz'])
23572376

0 commit comments

Comments
 (0)