2016-06-17 6 views
0

Ich habe mit Pandas in Python zwei Datenrahmen gemacht:Ändern den Wert in einem Datenrahmen Spalte auf dem Wert von zwei Spalten in einem diffrent Datenrahmen je

df1 

id business state inBusiness 
1  painter  AL  no 
2  insurance AL  no 
3  lawyer  OH  no 
4  dentist  NY  yes 
........... 

df2 

id business state 
1  painter  NY 
2  painter  AL 
3  builder  TX 
4  painter  AL  
...... 

Grundsätzlich mag ich Wert des ‚InBusiness‘ setzen in df1 auf 'yes', wenn in df2 eine Instanz der genau gleichen Kombination aus Geschäft und Standort existiert.

Wenn zum Beispiel painter/AL in df2 existiert, dann wird für alle Instanzen von painter/AL in df1 der Wert 'inBusiness' auf yes gesetzt.

Das Beste, was ich mit jetzt kommen kann, ist dies:

for index, row in df2.iterrows(): 
    df1[ (df1.business==str(row['business'])) & (df1.state==str(row['state']))]['inBusiness'] = 'Yes' 

aber der erste Datenrahmen kann potenziell Hunderttausende von Zeilen Schleife hat für jede Zeile durch in dem zweiten Datenrahmen so dass diese Methode nicht ist sehr zuverlässig. Gibt es einen schönen One-Liner, den ich hier verwenden kann, der auch schnell wäre?

+0

. @ Grün kombinieren zwei Spalten, wo Sie etwas wie painterNY in beiden Tabellen haben dann "JOIN" die beiden Tabellen. – Merlin

Antwort

1

Wahrscheinlich effizienteste eine Karte

inBusiness = {(business,state): 'yes' 
       for business,state in zip(df2['business'],df2['state'])} 
df1['inBusiness'] = [ inBusiness.get((business,state),"no") 
        for business,state in zip(df1['business'],df1['state'])] 
df1 

OUTPUT

id business state inBusiness 
0 1 painter  AL yes 
1 2 insurance AL no 
2 3 lawyer  OH no 
3 4 dentist  NY no 

Erklärung bearbeiten zu erstellen:

Sie waren vage über „erklärt weiter,“ so dass ich ein hohes Maß an alles geben würde

Die eingebauten in zip Funktion, die zwei Iterables (wie zwei Listen oder zwei Serien) und „Reißverschluss“ sie nimmt zusammen in Tupel.

a = [1,2,3] 
b = ['a','b','c'] 
for tup in zip(a,b): print(tup) 

Ausgänge:

(1, 'a') 
(2, 'b') 
(3, 'c') 

Zusätzlich können Tupel in Python "ausgepackt" in einzelne Variablen

tup = (3,4) 
x,y = tup 
print(x) 
print(y) 

Sie können diese beiden Dinge kombinieren dictionary comprehensions

newDict = {k: v for k,v in zip(a,b)} 
newDict 
erstellen

Ausgänge:

{1: 'a', 2: 'b', 3: 'c'} 

inBusiness ist ein Python-Wörterbuch ein Wörterbuch Verständnis erstellt nach zusammen, um die Serie von df2['business'] und df2['state'] zippen.

Ich musste eigentlich nicht die Variablen entpacken, aber ich tat es für das, was ich für Klarheit hielt.

Beachten Sie, dass diese Karte nur die Hälfte dessen ist, was Sie tun, weil jeder Schlüssel (business,state) im Wörterbuch auf verweist. Zum Glück ist dict.get Lassen Sie uns specify a default value zurück, wenn der Schlüssel nicht, welche in Ihrem Fall ist found- ist "no"

Dann wird die gewünschte Spalte erstellt eine Liste Verständnis mit dem gewünschten Ergebnis zu erzielen.

Deckt das alles ab?

+0

Kannst du erklären, wie das etwas genauer funktioniert? – GreenGodot

+0

Perfekt! Ich wollte nur absolut sicher sein, dass ich hatte, was das in meinem Kopf macht. – GreenGodot

2

könnten Sie verwenden .merge(how='left', indicator=True) (indicator in pandas>=0.17 hinzugefügt wurde, see docs) Spalten sowie die Quelle des Spiels zu identifizieren passende etwas in dieser Richtung zu erhalten:

df1.merge(df2, how='left', indicator=True) # merges by default on shared columns 

    id business state inBusiness  _merge 
0 1 painter AL   no  both 
1 2 insurance AL   no left_only 
2 3  lawyer OH   no left_only 
3 4 dentist NY  yes left_only 

Die _merge gibt an, in welchen Fällen die (business, state) Kombinationen sind sowohl in df1 als auch in df2 verfügbar. Dann brauchen Sie nur zu:

df['inBusiness'] = df._merge == 'both' 

zu erhalten:

id business state inBusiness  _merge 
0 1 painter AL  True  both 
1 2 insurance AL  False left_only 
2 3  lawyer OH  False left_only 
3 4 dentist NY  False left_only