2016-07-08 4 views
1

Ich versuche in Python/Pandas zu replizieren, was in SQL ziemlich einfach wäre, aber stecken geblieben.Machen Sie einen inneren Beitritt in Python Pandas mit Kriterien

Ich möchte mit drei Spalten einen Datenrahmen zu übernehmen:

dataframe1 

    Org Des Score 
0 A B 10 
1 A B 11 
2 A B 15 
3 A C 4 
4 A C 4.5 
5 A C 6 
6 A D 100 
7 A D 110 
8 A D 130 

Und alle Scorewerte herauszufiltern, die größer sind als die Mindest * 1.2 für jede Org-Des-Kombination.

So würde die Ausgabetabelle sein:

output_dataframe 

    Org Des Score 
0 A B 10 
1 A B 11 
3 A C 4 
4 A C 4.5 
6 A D 100 
7 A D 110 

Zur ersten Org-Des-Combo, AB, ist die min Score 10 und (1,2 * min) = 12. So Zeilen 0 und 1 würden erhalten bleiben weil die Punkte 10 und 11 < sind. Zeile 3 würde eliminiert werden, weil sie> 12 ist.

Für AC ist der min Score 4 und (1,2 * min) = 5. Also Zeilen 3 und 4 bleiben erhalten, weil sie sind < 5. Und so weiter ...

Mein Ansatz

Ich dachte, ich den folgenden Ansatz verwenden würde:

  1. Verwenden Sie eine groupby Funktion einen Datenrahmen mit den Minuten mit dem Org-Dem Paar zu erstellen:

    dataframe2 = pd.DataFrame(dataframe1.groupby(['Org','Des'])['Score'].min()) 
    
  2. Dann tun ein innerer Join (oder eine Zusammenführung?) zwischen Dataframe1 und Dataframe2 mit den Kriterien, dass der Score < 1.2 * min für jeden Org-Des-Paartyp ist.

Aber ich habe nicht in der Lage zu bekommen dies aus zwei Gründen zu arbeiten, 1) dataframe2 endet eine funky Form zu sein, die ich brauchen würde, um herauszufinden, wie mit dataframe1 zu verbinden oder zu fusionieren, oder verwandeln dann Join/merge und 2) Ich weiß nicht, wie man Kriterien als Teil eines Joins/merge festlegen.

Ist dies der richtige Ansatz oder gibt es einen pythischeren Weg, um das gleiche Ziel zu erreichen?

bearbeiten zu reflektieren @Psidom Antwort:

ich den Code versucht, die Sie vorgeschlagen und es gab mir einen Fehler, hier ist der vollständige Code und Ausgabe:

In: import pandas as pd 
    import numpy as np 

In: df1 = pd.DataFrame({'Org': ['A','A','A','A','A','A','A','A','A'], 
         'Des': ['B','B','B','C','C','C','D','D','D'], 
         'Score': ['10','11','15','4','4.5','6','100','110','130'], }) 

Out: Org Des Score 
    0 A B 10 
    1 A B 11 
    2 A B 15 
    3 A C 4 
    4 A C 4.5 
    5 A C 6 
    6 A D 100 
    7 A D 110 
    8 A D 130 

In: df2 = pd.DataFrame(df1.groupby(['Org','Des'])['Score'].min()) 
    df2 

Out:  Score 
    Org Des 
    A B 10 
     C 4 
     D 100 

In: df1 = pd.merge(df1, df2.groupby(['Org', 'Des']).min()*1.2, left_on = ['Org', 'Des'], right_index=True) 
    df.loc[df1.Score_x < df1.Score_y, :] 

Out: KeyError: 'Org' #It's a big error but this seems to be the relevant part. Let me know if it would be useful to past the whole error. 

ich vermute ich, die haben df1, df2 und df sind durcheinander? Ich habe den ursprünglichen Antwortposten geändert, um ihn dem Code anzupassen.

Antwort

2

Sie können die Verknüpfungskriterien wie folgt einrichten.Für den Original-Datenrahmen, stellen Sie die Join-Spalten als ['Org', 'Des'], und für den aggregierten Datenrahmen der gruppierten Spalten-Index werden, so dass Sie right_index einstellen müssen wahr sein, dann sollte es funktionieren wie erwartet:

import pandas as pd 
df1 = pd.DataFrame({'Org': ['A','A','A','A','A','A','A','A','A'], 
        'Des': ['B','B','B','C','C','C','D','D','D'], 
        'Score': [10,11,15,4,4.5,6,100,110,130]}) 
df2 = pd.DataFrame(df1.groupby(['Org','Des'])['Score'].min()) 

df3 = pd.merge(df1, df2, left_on = ['Org', 'Des'], right_index=True) 
df1.loc[df3.Score_x < df3.Score_y * 1.2, ] 

# Org Des Score 
#0 A B 10.0 
#1 A B 11.0 
#3 A C 4.0 
#4 A C 4.5 
#6 A D 100.0 
#7 A D 110.0 
+0

habe ich versucht, den Code, den Sie vorgeschlagen und bearbeitet über die Frage a) der vollständige Code mir es geben ich verwende und b) der Fehler zu reflektieren. Irgendeine Idee, was ich falsch gemacht habe? Beachten Sie, dass ich die df-Namen in Ihrem Code geändert habe, damit sie mit meinen Datenrahmen übereinstimmen. Ich habe vielleicht etwas verpasst. – RJH2

+0

Nur die Antwort reproduzierbar gemacht, Sie haben den Fehler, weil Sie die 'groupby min()' zweimal berechnet. Wenn Ihr 'df2' bereits durch die 'groupby-min'-Operation berechnet wurde, müssen Sie diese nur an die zweite Position von' pd.merge() 'übergeben. – Psidom

+0

Das hat funktioniert, danke! Außerdem habe ich meinen ursprünglichen Beitrag bearbeitet, bei dem ich die Scores-Spalte fälschlicherweise als Streichergruppe erstellt habe. Das gab mir einen Fehler. Sie als Werte einzugeben, hat es behoben. – RJH2

2

I tat es wie folgt aus:

df[df.groupby(['Org', 'Des']).Score.apply(lambda x: x < x.min() * 1.2)] 

enter image description here

+0

Das ist glatt. Ich kenne Lambda-Funktionen nicht, aber das hat tatsächlich funktioniert. Mit weniger Code. Wird Lambdas untersuchen. Außerdem wurde das Größer-als-Weniger-Zeichen umgekehrt, so dass es die gegenteilige Antwort gab, aber das Spiegeln funktionierte. – RJH2

+0

@ RJH2 Feste Post. – piRSquared

Verwandte Themen