2017-05-01 32 views
3

Ich habe zwei Datenrahmen wie dieseSubtrahierend Datenrahmen mit ungleicher Anzahl von Zeilen

import pandas as pd 
import numpy as np 

np.random.seed(0) 

df1 = pd.DataFrame(np.random.randint(10, size=(5, 4)), index=list('ABCDE'), columns=list('abcd')) 
df2 = pd.DataFrame(np.random.randint(10, size=(2, 4)), index=list('CE'), columns=list('abcd')) 

    a b c d 
A 5 0 3 3 
B 7 9 3 5 
C 2 4 7 6 
D 8 8 1 6 
E 7 7 8 1 

    a b c d 
C 5 9 8 9 
E 4 3 0 3 

Der Index der df2 ist immer eine Teilmenge des Index der df1 und die Spaltennamen identisch sind.

Ich möchte einen dritten Datenrahmen erstellen df3 = df1 - df2. Wenn man das tut, erhält man

 a b c d 
A NaN NaN NaN NaN 
B NaN NaN NaN NaN 
C -3.0 -5.0 -1.0 -3.0 
D NaN NaN NaN NaN 
E 3.0 4.0 8.0 -2.0 

Ich habe nicht die NAs im ouput will, aber die jeweiligen Werte von df1. Gibt es eine kluge Art, z.B. fillna mit den Werten df1 in den Zeilen, die nicht in df2 enthalten sind?

wäre Eine Abhilfe wie nur die erforderlichen Zeilen die subtrahieren zu tun:

sub_ind = df2.index 
df3 = df1.copy() 
df3.loc[sub_ind, :] = df1.loc[sub_ind, :] - df2.loc[sub_ind, :] 

, die mir die gewünschte Ausgabe

a b c d 
A 5 0 3 3 
B 7 9 3 5 
C -3 -5 -1 -3 
D 8 8 1 6 
E 3 4 8 -2 

aber vielleicht gibt eine einfache Möglichkeit, dies zu erreichen, gibt es?

+0

Was ist los mit 'df1-df2'? Ist das nicht Ihre gewünschte Ausgabe? – blacksite

+0

Nein, ich will nicht die NAs aber die Werte von df1; Ich aktualisiere die Fragen. – Cleb

Antwort

2

Wenn Sie die sub Methode anstelle von -, können Sie einen Füllwerts passieren:

df1.sub(df2, fill_value=0) 
Out: 
    a b c d 
A 5.0 0.0 3.0 3.0 
B 7.0 9.0 3.0 5.0 
C -3.0 -5.0 -1.0 -3.0 
D 8.0 8.0 1.0 6.0 
E 3.0 4.0 8.0 -2.0 
+0

Funktioniert gut, danke (upvoted)! Gibt es eine Idee, ob "sub" effizienter ist als "df1-df2" wie in @ not_a_robots Antwort? – Cleb

+0

Hat eine schnelle Überprüfung und scheint Ihre Lösung ist viel schneller. – Cleb

+1

Ja, ich habe es auch nicht auf einem großen Datensatz getestet, aber für kleine scheint das schneller. – ayhan

3

Ich denke, das ist das, was Sie wollen:

(df1-df2).fillna(df1) 

Out[40]: 
    a b c d 
A 5.0 0.0 3.0 3.0 
B 7.0 9.0 3.0 5.0 
C -3.0 -5.0 -1.0 -3.0 
D 8.0 8.0 1.0 6.0 
E 3.0 4.0 8.0 -2.0 

subtrahieren Sie einfach den Datenrahmen, wie Sie es normalerweise, aber „Paket“ das Ergebnis Klammer verwenden und die pandas.DataFrame.fillna Methode auf dem Ergebnis führen. Oder ein bisschen mehr verbosely:

diff = df1-df2 
diff.fillna(df1, inplace=True) 
+0

Funktioniert gut, danke (upvoted)! – Cleb

2

Hier ist eine Option mit reindex und seine fill_value Parameter. Die wichtigsten Unterschiede zwischen dieser Antwort und @ ayhan Antwort lautet:

  • Sie den Füllwerts ein nur der Datenrahmen oder beide
  • steuern kann dies zu reindex über eine Zollunion der Indizes von df1 verallgemeinert werden könnten und df2
  • Wir haben eine bessere Kontrolle des int Datentyp

df1 - df2.reindex(df1.index, fill_value=0) 

    a b c d 
A 5 0 3 3 
B 7 9 3 5 
C -3 -5 -1 -3 
D 8 8 1 6 
E 3 4 8 -2 
zu erhalten
+1

Schön (upvoted), das scheint sogar schneller als @ ayhans Lösung. – Cleb

Verwandte Themen