/ / Python-Pandas-Gruppe basierend auf Spalte und Maximum erhalten, aber basierend auf einer anderen Spalte - Python, Pandas

Python Pandas Gruppe basierend auf Spalte und erhalten max, aber basierend auf einer anderen Spalte - Python, Pandas

Ich arbeite mit ein paar Daten und würde gerne ziehendas Maximum für eine bestimmte Spalte, gruppiert nach einer anderen Spalte. Ich möchte jedoch bestimmte Zeilen aus der maximalen Berechnung ausschließen, die auf einer anderen Spalte basieren.

Beispiel:

df = pd.DataFrame({"Col1":["A","A","A","B","B","B","B"],
"Col2":["Build","Plan","Other","Test","Build","Other","Buy"],
"Col3":[2,5,17,5,13,12,12]})

Ich möchte das Maximum von Col3 erhalten, gruppiert nach Col1, wobei alle Zeilen ausgeschlossen werden, die in Col2 "Other" enthalten. Das Maximum von Col3 für "A" sollte also 5 sein, nicht 17.

Ich konnte das Maximum von Col3 nach Col1 gruppieren. df["new"] = df.groupby(["Col1"])["Col3"].transform(max) Dies gibt mir jedoch einen Wert von 17 für A.

Ich habe mich in anderen Threads umgesehen:

x = df1.groupby(["Col1"])
x2 = x.apply(lambda g: g[g["Col2"] != "Other"])

und dies scheint mir nahe zu kommen (es hat die Daten nach Col1 gruppiert und die Zeilen wurden basierend auf Col2 entfernt). Ich finde jedoch keinen Weg mehr, das Maximum von Col3 basierend auf Col1 zu erreichen.

Am besten konnte ich verwenden: x2["Col3"].max() um das Maximum von Col3 zu erhalten, nachdem alle Zeilen mit "Other" in Col2 entfernt wurden Ich kann jedoch nicht das Maximum von Col3 nach Col1 gruppieren.

Ich habe mich gefragt, ob es eine Möglichkeit gibt, eingebaute Pandas-Funktionen zu verwenden, um dies relativ einfach zu tun, anstatt eine völlig neue, maßgeschneiderte Funktion zu erstellen.

Antworten:

3 für die Antwort № 1

Du kannst es versuchen

df[df.Col2 != "Other"].groupby("Col1").Col3.max()

Col1
A     5
B    13

So erstellen Sie eine neue Spalte:

df["new"]=df[df.Col2 != "Other"].groupby("Col1").Col3.transform("max")
df["new"] = df.new.ffill()

Col1    Col2    Col3    new
0   A       Build   2       5.0
1   A       Plan    5       5.0
2   A       Other   17      5.0
3   B       Test    5       13.0
4   B       Build   13      13.0
5   B       Other   12      13.0
6   B       Buy     12      13.0

Erläuterung: Wählen Sie nur die Zeilen der df aus, bei denen der Col2-Wert nicht gleich "Other" ist.

Hier ist die Dokumentation von transform: Es gibt ein ähnlich indiziertes df mit transformierten Werten zurück, anstatt zu aggregieren.


1 für die Antwort № 2

Eine andere Möglichkeit, es mit zu verwechseln groupby

df.groupby([df.Col2.ne("Other"), "Col1"]).Col3.max()[True]

Col1
A     5
B    13
Name: Col3, dtype: int64

0 für die Antwort № 3

Die Antwort von @Vaishali ist ein guter Anfang, aber ichIch denke, es kann einige Probleme haben, vor allem wenn Sie ffill anwenden, um Na loszuwerden. Damit diese Methode funktioniert, müssen Sie Ihren Datenrahmen besonders sortieren. Um überzeugt zu sein, probieren Sie folgendes:

df = pd.DataFrame({"Col1":["A","A","A","B","B","B","B","C", "C"],
"Col2":["Build","Plan","Other","Test","Build","Other","Buy", "Buy","Other"],
"Col3":[2,5,17,5,13,12,12,14,5]})
df = df.sample(frac=1) #shuffle rows

df["new"]=df[df.Col2 != "Other"].groupby("Col1")["Col3"].transform("max")
df["new"] = df.new.ffill()

Und Sie können diese Ergebnisse erhalten, die nicht gut sind.

Col1    Col2    Col3    new
3   B   Test    5   13.0
7   C   Buy     14  14.0
6   B   Buy     12  13.0
1   A   Plan    5   5.0
0   A   Build   2   5.0
5   B   Other   12  5.0
8   C   Other   5   5.0
4   B   Build   13  13.0
2   A   Other   17  13.0

Eine bessere Lösung: Definieren Sie zuerst diese Funktion.

def new_transform(df, exclude_cond,gbycol,target, agg_fun, ignore_value=None):
df["target_temp"] = df[target]
df.loc[eval(exclude_cond), "target_temp"] = ignore_value
tmp=df.groupby(gbycol)["target_temp"].transform(agg_fun)
df.drop("target_temp", axis=1, inplace=True)
return tmp

Es wird Ihr Datenrahmen, Ihre exculde_cond alsZeichenfolge, Ihre Gruppe als Liste von Zeichenfolgen oder eine Zeichenfolge, der Name der Zielspalte, für die die Berechnung ausgeführt wird, die Aggregationsfunktion und einen von der Aggregationsfunktion ignorierten Wert (Keine wird für die wichtigsten Agg-Funktionen verwendet)

Beispiel:

df = pd.DataFrame({"Col1":["A","A","A","B","B","B","B","C", "C"],
"Col2":["Build","Plan","Other","Test","Build","Other","Buy", "Buy","Other"],
"Col3":[2,5,17,5,13,12,12,14,5]})
df = df.sample(frac=1)
df["new"]=new_transform(df, "df["Col2"]=="Build"", ["Col1"],"Col3", "sum", np.nan)

Wir bekommen die richtigen Berechnungen:

  Col1  Col2    Col3    new
3   B   Test    5     29.0
2   A   Other   17    22.0
4   B   Build   13    29.0
6   B   Buy     12    29.0
7   C   Buy     14    19.0
1   A   Plan    5     22.0
5   B   Other   12    29.0
0   A   Build   2     22.0
8   C   Other   5     19.0