Kiedy piszesz
a.loc[1,'b'] = b
i b
to seria, indeks b
musi dokładnie pasować do indeksowania generowane przez a.loc[1,'b']
celem dla wartości w b
zostać skopiowany do a
. Okazuje się jednak, że gdy a.columns
jest MultiIndex
, the indexer for a.loc[1,'b']
jest:
(Pdb) p new_ix
Index([(u'b', 0), (u'b', 1)], dtype='object')
natomiast indeks b
jest
(Pdb) p ser.index
Int64Index([0, 1], dtype='int64')
Oni nie pasują do siebie, a zatem
(Pdb) p ser.index.equals(new_ix)
False
Ponieważ wartości nie są wyrównane, the code branch you fall into przydziela
(Pdb) p ser.reindex(new_ix).values
array([ nan, nan])
Znalazłem to dodając pdb.set_trace()
do kodu:
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
i po prostu stepping przez niego na "wysokim poziomie" i znalezienie the problem occurs in
if isinstance(value, ABCSeries):
value = self._align_series(indexer, value)
a następnie wzmocnienie przez nią ponownie (z grzebieniem o drobniejszym uzębieniu) z punktem przerwania rozpoczynającym się na linii wywołującej self._align_series(indexer, value)
.
Zauważ, że jeśli zmieni indeks b
być również MultiIndex:
b = pd.Series([13.0, 15.0], index=pd.MultiIndex.from_product([['b'], [0,1]]))
następnie
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)
daje
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
W moim przypadku 'b' jest w rzeczywistości tymczasową serią uzyskaną z cięcia innej ramki DataFrame (bez MultiIndex). Czy istnieje sposób rozwiązania tego problemu bez przechowywania tymczasowej serii i ponownego jej indeksowania? – MindV0rtex
Myślę, że najłatwiejsze rozwiązanie to to, które pokazałeś - przypisz obiekt nieindeksowany: 'a.loc [1, 'b'] = b.values'. – unutbu