Когда вы пишете
a.loc[1,'b'] = b
и b
является серия, индекс b
должен точно соответствовать индексатор, порожденную a.loc[1,'b']
для того, чтобы значения в b
быть скопирован в a
. Оказывается, однако, что, когда a.columns
является MultiIndex
, the indexer for a.loc[1,'b']
является:
(Pdb) p new_ix
Index([(u'b', 0), (u'b', 1)], dtype='object')
в то время как индекс для b
является
(Pdb) p ser.index
Int64Index([0, 1], dtype='int64')
Они не совпадают, и поэтому
(Pdb) p ser.index.equals(new_ix)
False
Поскольку значения не выровнены, the code branch you fall into присваивает
(Pdb) p ser.reindex(new_ix).values
array([ nan, nan])
Я нашел это, добавив pdb.set_trace()
к коду:
import pandas as pd
columns = pd.MultiIndex.from_product([['a', 'b', 'c'], range(2)])
a = pd.DataFrame(0.0, index=range(3),columns=columns, dtype='float')
b = pd.Series([13.0, 15.0])
import pdb
pdb.set_trace()
a.loc[1,'b'] = b # this line results in NaNs
a.loc[1,'b'] = b.values # this yields correct behavior
и просто шагая через него на «высоком уровне» и найти the problem occurs in
if isinstance(value, ABCSeries):
value = self._align_series(indexer, value)
, а затем шагать через него снова (с более тонкой зубчатой гребенкой) с точкой останова, начинающейся с линии, вызывающей self._align_series(indexer, value)
.
Обратите внимание, что при изменении индекса b
также быть мультииндексным:
b = pd.Series([13.0, 15.0], index=pd.MultiIndex.from_product([['b'], [0,1]]))
затем
import pandas as pd
columns = pd.MultiIndex.from_product([['a', 'b', 'c'], range(2)])
a = pd.DataFrame(0.0, index=range(3),columns=columns, dtype='float')
b = pd.Series([13.0, 15.0], index=pd.MultiIndex.from_product([['b'], [0,1]]))
a.loc[1,'b'] = b
print(a)
дает
a b c
0 1 0 1 0 1
0 0 0 0 0 0 0
1 0 0 13 15 0 0
2 0 0 0 0 0 0
В моем случае 'b' на самом деле является временной серией, полученной нарезкой другого DataFrame (без MultiIndex). Есть ли способ решить эту проблему, не сохранив эту временную серию и переиндексируя ее? – MindV0rtex
Я думаю, что самое легкое обходное решение - это тот, который вы показали - назначить неиндексированный объект: 'a.loc [1, 'b'] = b.values'. – unutbu