Quando si scrive
a.loc[1,'b'] = b
e b
è una serie, l'indice di b
deve corrispondere esattamente l'indicizzatore generato da a.loc[1,'b']
in modo che i valori in b
essere copiati nella a
. Risulta, tuttavia, che quando è un a.columns
MultiIndex
, the indexer for a.loc[1,'b']
è:
(Pdb) p new_ix
Index([(u'b', 0), (u'b', 1)], dtype='object')
mentre l'indice di b
è
(Pdb) p ser.index
Int64Index([0, 1], dtype='int64')
Essi non corrispondono, e quindi
(Pdb) p ser.index.equals(new_ix)
False
Poiché i valori non sono allineati, the code branch you fall into assegna
(Pdb) p ser.reindex(new_ix).values
array([ nan, nan])
ho trovato questo con l'aggiunta di pdb.set_trace()
al codice:
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
e semplicemente fare un passo attraverso di essa ad un "alto livello" e trovare the problem occurs in
if isinstance(value, ABCSeries):
value = self._align_series(indexer, value)
e poi passando attraverso di nuovo (con un pettine a denti più fini) con un punto di rottura a partire dalla linea che chiama self._align_series(indexer, value)
.
Si noti che se si cambia l'indice di b
di essere anche un MultiIndex:
b = pd.Series([13.0, 15.0], index=pd.MultiIndex.from_product([['b'], [0,1]]))
poi
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)
produce
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
Nel mio caso, 'b' è in realtà una serie temporanea ottenuta dall'affettare un altro DataFrame (senza MultiIndex). C'è un modo per risolvere questo senza archiviare quella serie temporanea e reindicarla? – MindV0rtex
Penso che la soluzione più semplice sia quella che hai mostrato - assegna un oggetto non indicizzato: 'a.loc [1, 'b'] = b.values'. – unutbu