/ / Python pandas groupby podmienené zřetězenie reťazcov do viacerých stĺpcov - python, panda, group-by, podmienené, string-zlučovanie

Python pandas groupby podmienene zoskupuje reťazce do viacerých stĺpcov - python, panda, group-by, podmienené, string-zlučovanie

Snažím sa zoskupiť jeden dátový rámecstĺpec, pričom niekoľko stĺpcov z jedného riadku v každej skupine a reťazenie reťazcov z ostatných riadkov do viacerých stĺpcov na základe hodnoty jedného stĺpca. Tu je príklad ...

df = pd.DataFrame({"test" : ["a","a","a","a","a","a","b","b","b","b"],
"name" : ["aa","ab","ac","ad","ae","ba","bb","bc","bd","be"],
"amount" : [1, 2, 3, 4, 5, 6, 7, 8, 9, 9.5],
"role" : ["x","y","y","x","x","z","y","y","z","y"]})

df

      amount    name    role    test
0        1.0    aa      x       a
1        2.0    ab      y       a
2        3.0    ac      y       a
3        4.0    ad      x       a
4        5.0    ae      x       a
5        6.0    ba      z       a
6        7.0    bb      y       b
7        8.0    bc      y       b
8        9.0    bd      z       b
9        9.5    be      y       b

Chcel by som sa zorganizovať na skúške, ponechať meno akeď rolu = "z", vytvoríme stĺpec (nazveme ho X), ktorý zlučuje hodnoty názvu, keď rolu = "x" a iného stĺpca (necháme ho nazvať Y), ktorý zlučuje hodnoty názvu = "y". [Zlučiteľné hodnoty oddelené znakom ";"] Mohlo by existovať nula až veľa riadkov s rolou = "x", nula až mnohými riadkami s rolou = "y" a jedným riadkom s rolou = "z" na hodnotu testu. Pre X a Y tieto môžu byť nulové, ak neexistujú žiadne riadky pre túto úlohu pre tento test. Hodnota sumy sa zruší pre všetky riadky s rolou = "x" alebo "y". Požadovaný výkon by bol niečo ako:

     test   name     amount        X              Y
0    a      ba          6.0        aa; ad; ae     ab; ac
1    b      bd          9.0        None           bb; bc; be

Pre zlučujúcu sa časť som našiel x.ix[x.role == "x", X] = "{%s}" % "; ".join(x["name"]), ktoré môžem zopakovať pre y. Snažil som sa niekoľko vecí name = x[x.role == "z"].name.first() pre názov a čiastku. Taktiež som sa pokúsil zísť na obe cesty definovanej funkcie a funkciu lambda bez úspechu. Oceniť akékoľvek myšlienky.

odpovede:

1 pre odpoveď č. 1

Môžete vytvoriť prispôsobené stĺpce v apply funkcia po groupby kde: g môže byť považovaný za podradený dátový rámec s jednou hodnotou v testovacom stĺpci a keďže chcete vrátiť viac stĺpcov, musíte vytvoriť Series objekt pre každú skupinu, kde indexy sú vo výsledku zodpovedajúce hlavičky:

df.groupby("test").apply(lambda g: pd.Series({"name": g["name"][g.role == "z"].iloc[0],
"amount": g["amount"][g.role == "z"].iloc[0],
"X": "; ".join(g["name"][g.role == "x"]),
"Y": "; ".join(g["name"][g.role == "y"])
})).reset_index()

tu zadajte popis obrázku


1 pre odpoveď č. 2
# set index and get crossection where test is "z"
z = df.set_index(["test", "role"]).xs("z", level="role")
# get rid of "z" rows and group by "test" and "role" to join names
xy = df.query("role != "z"").groupby(["test", "role"])["name"].apply(";".join).unstack()
# make columns of xy upper case
xy.columns = xy.columns.str.upper()

pd.concat([z, xy], axis=1).reset_index()

tu zadajte popis obrázku