2016-05-23 18 views
10

Sto tentando di aggiornare un paio di campi contemporaneamente: ho due origini dati e sto cercando di riconciliarle. So che potrei fare un po 'brutto fusione e quindi eliminare le colonne, ma mi aspettavo questo codice qui sotto a lavorare:Pandas aggiorna più colonne contemporaneamente

df = pd.DataFrame([['A','B','C',np.nan,np.nan,np.nan], 
        ['D','E','F',np.nan,np.nan,np.nan],[np.nan,np.nan,np.nan,'a','b','d'], 
        [np.nan,np.nan,np.nan,'d','e','f']], columns = ['Col1','Col2','Col3','col1_v2','col2_v2','col3_v2']) 

print df 

Col1 Col2 Col3 col1_v2 col2_v2 col3_v2 
0 A B C  NaN  NaN  NaN 
1 D E F  NaN  NaN  NaN 
2 NaN NaN NaN  a  b  d 
3 NaN NaN NaN  d  e  f 

#update 
df.loc[df['Col1'].isnull(),['Col1','Col2', 'Col3']] = df[['col1_v2','col2_v2','col3_v2']] 

print df 

Col1 Col2 Col3 col1_v2 col2_v2 col3_v2 
0 A B C  NaN  NaN  NaN 
1 D E F  NaN  NaN  NaN 
2 NaN NaN NaN  a  b  d 
3 NaN NaN NaN  d  e  f 

mio output desiderato sarebbe:

Col1 Col2 Col3 col1_v2 col2_v2 col3_v2 
0 A B C  NaN  NaN  NaN 
1 D E F  NaN  NaN  NaN 
2 a b c  a  b  d 
3 d e f  d  e  f 

Sto scommettendo che ha a che fare con aggiornamento/impostazione su una sezione, ma uso sempre .loc per aggiornare i valori, ma non su più colonne contemporaneamente.

Mi sento come se ci fosse un modo semplice per fare questo che mi manca, qualsiasi pensiero/suggerimento sarebbe benvenuto!

Modifica per riflettere la soluzione di seguito Grazie per il commento sugli indici. Tuttavia, ho una domanda su questo in quanto riguarda le serie. Se volessi aggiornare una singola serie in un modo simile, avrei potuto fare qualcosa di simile:

df.loc[df['Col1'].isnull(),['Col1']] = df['col1_v2'] 

print df 

    Col1 Col2 Col3 col1_v2 col2_v2 col3_v2 
0 A B C  NaN  NaN  NaN 
1 D E F  NaN  NaN  NaN 
2 a NaN NaN  a  b  d 
3 d NaN NaN  d  e  f 

Nota che non ho conto per gli indici qui, ho filtrato ad una serie 2x1 e impostare la parità a una serie 4x1, ma gestita correttamente. Pensieri? Sto cercando di comprendere la funzionalità un po 'meglio di qualcosa che ho usato per un po', ma credo che non avere una conoscenza completa del meccanismo sottostante/regola

+1

Il lato destro di tale assegnazione è un 'pd.Series' senza informazioni sulla colonna. Le informazioni di questa colonna sono state inserite nell'attributo 'name' dell'oggetto 'pd.Series'. Quando si effettua l'assegnazione, si ignora l'allineamento delle colonne e si inserisce semplicemente la serie specificata nella colonna specificata. Prova 'df.loc [df ['Col1'].isnull(), ['Col1', 'Col2']] = df ['col1_v2'] 'e vediamo che lascia solo quella serie in entrambe le colonne specificate ora. Per poter assegnare alle colonne corrette ** ** le colonne corrette, devi chiamare correttamente le colonne. Altrimenti, loop. – piRSquared

+0

Vorrei anche aggiungere che se invece hai fatto 'df.loc [df ['Col1']. Isnull(), ['Col1']] = df [['col1_v2']]' con doppie parentesi attorno a 'col_v2' , questo proverebbe a spingere un dataframe in quella colonna che dovrebbe metterti nella stessa situazione di prima. Ciò dimostra ulteriormente la differenza tra l'assegnazione di una serie rispetto a un dataframe. – piRSquared

risposta

8

si desidera sostituire

print df.loc[df['Col1'].isnull(),['Col1','Col2', 'Col3']] 

    Col1 Col2 Col3 
2 NaN NaN NaN 
3 NaN NaN NaN 

Con:

replace_with_this = df.loc[df['Col1'].isnull(),['col1_v2','col2_v2', 'col3_v2']] 
print replace_with_this 

    col1_v2 col2_v2 col3_v2 
2  a  b  d 
3  d  e  f 

sembra ragionevole. Tuttavia, quando si esegue l'assegnazione, è necessario tenere conto dell'allineamento dell'indice, che include le colonne.

Quindi, questo dovrebbe funzionare:

df.loc[df['Col1'].isnull(),['Col1','Col2', 'Col3']] = replace_with_this.values 

print df 

    Col1 Col2 Col3 col1_v2 col2_v2 col3_v2 
0 A B C  NaN  NaN  NaN 
1 D E F  NaN  NaN  NaN 
2 a b d  a  b  d 
3 d e f  d  e  f 

ho rappresentato per colonne utilizzando .values alla fine. Ciò ha rimosso le informazioni sulla colonna dal dataframe replace_with_this e ha semplicemente utilizzato i valori nelle posizioni appropriate.

+0

Grazie - aggiunta modifica sopra per la tua soluzione, pensieri su questo? – flyingmeatball

2

Nello spirito "prendi la collina", offro la soluzione seguente che fornisce il risultato richiesto.

Mi rendo conto che questo non è esattamente ciò che si cerca poiché non sto affettando il df (nel modo ragionevole, ma non funzionale, in cui si propone).

#Does not work when indexing on np.nan, so I fill with some arbitrary value. 
df = df.fillna('AAA') 

#mask to determine which rows to update 
mask = df['Col1'] == 'AAA' 

#dict with key value pairs for columns to be updated 
mp = {'Col1':'col1_v2','Col2':'col2_v2','Col3':'col3_v2'} 

#update 
for k in mp: 
    df.loc[mask,k] = df[mp.get(k)] 

#swap back np.nans for the arbitrary values 
df = df.replace('AAA',np.nan) 

uscita:

Col1 Col2 Col3 col1_v2  col2_v2  col3_v2 
A  B  C  NaN   NaN   NaN 
D  E  F  NaN   NaN   NaN 
a  b  d  a   b   d 
d  e  f  d   e   f 

L'errore che ottengo se non si sostituisce nans è sotto. Sto andando a ricercare esattamente da dove proviene questo errore.

ValueError: array is not broadcastable to correct shape 
Problemi correlati