Pandas gruppieren nach Ergebnis in Spalten

8

Ich habe einen Datenrahmen wie diesen:

x = pd.DataFrame({
    'audio': ['audio1', 'audio1', 'audio2', 'audio2', 'audio3', 'audio3'],
    'text': ['text1', 'text2', 'text3', 'text4', 'text5', 'text6'],
    'login': ['operator1', 'operator2', 'operator3', 'operator4', 'operator5', 'operator6'] 
})

Ich versuche es so zu aggregieren:

x1 = x.groupby('audio')['text'].agg(
    [
    ('text1', lambda x : x.iat[0]),
    ('text2', lambda x : x.iat[1]),
    ('leven', lambda x: Levenshtein.distance(x.iat[0], x.iat[1])) #some function works with grouped text
    ]
).reset_index()

und es funktioniert, aber ich muss auch gruppierte Anmeldungen zur Zeile hinzufügen, um die Zeile wie folgt zu erstellen:

audio, text1, text2, leven, login1, login2

Ich habe so etwas versucht, lambda x : x.ait[0, 1]aber es funktioniert nicht

Contra111
quelle
Sind die Daten immer geordnet und in Paaren von zwei zusammengehörigen Zeilen?
Darkonaut

Antworten:

6

Wenn ich mir Ihren Datenrahmen anschaue, denke ich darüber nach, den Datenrahmen zu schwenken. Im Folgenden ist mein Ansatz aufgeführt, bei dem mit groupby().cumcount()und unstackmit einigen Spaltenformatierungen ein geschwenkter Datenrahmen erstellt wird.

Option 1: Dann können Sie df.applydie Funktion anwenden

m = x.assign(k=x.groupby('audio').cumcount().add(1)).set_index(['audio','k']).unstack()
m.columns=[f"{a}{b}" for a,b in m.columns]
m = m.assign(leven=m.apply(lambda x: 
              Levenshtein.distance(x['text1'],x['text2']),1)).reset_index()

    audio  text1  text2     login1     login2  leven
0  audio1  text1  text2  operator1  operator2      1
1  audio2  text3  text4  operator3  operator4      1
2  audio3  text5  text6  operator5  operator6      1

Option 2: ( Ich würde das vorziehen )

Sie können auch ein Listenverständnis verwenden, um dasselbe zu tun. Ersetzen Sie einfach die letzte Zeile durch:

m = x.assign(k=x.groupby('audio').cumcount().add(1)).set_index(['audio','k']).unstack()
m.columns=[f"{a}{b}" for a,b in m.columns]
m = m.assign(leven=[Levenshtein.distance(a,b) for 
               a,b in zip(m['text1'],m['text2'])]).reset_index()

    audio  text1  text2     login1     login2  leven
0  audio1  text1  text2  operator1  operator2      1
1  audio2  text3  text4  operator3  operator4      1
2  audio3  text5  text6  operator5  operator6      1

Option 3:

Wenn die Position der levenSpalte wichtig ist, können Sie Folgendes verwenden df.insert:

m=x.assign(k=x.groupby('audio').cumcount().add(1)).set_index(['audio','k']).unstack()
m.columns=[f"{a}{b}" for a,b in m.columns]
m.insert(2,'leven',[Levenshtein.distance(a,b) for a,b in zip(m['text1'],m['text2'])])
m=m.reset_index()

    audio  text1  text2  leven     login1     login2
0  audio1  text1  text2      1  operator1  operator2
1  audio2  text3  text4      1  operator3  operator4
2  audio3  text5  text6      1  operator5  operator6
anky
quelle
1
Schön, vielleicht möchten Sie einen Blick darauf werfen FuzzyWuzzy, um den Levenshtein-
Distanzalgorithmus
@Datanovice yep, aber ich glaube, OP verwendet dieses hier verwendet. egal welche
func
1
Antworte nett, ich denke du solltest +50 bekommen;)
jezrael
2

Suchst du danach:

x1 = x.groupby('audio',)['login'].agg(
     [
     ('operator1', lambda x : x.iat[0]),
     ('operator2', lambda x : x.iat[1]),
     ('leven', lambda x: Levenshtein.distance(x.iat[0], x.iat[1])) #some function works with grouped text
     ]
 ).reset_index()

 x2 = x.groupby('audio',)['text'].agg(
     [
     ('text1', lambda x : x.iat[0]),
     ('text2', lambda x : x.iat[1]),
     ('leven', lambda x: Levenshtein.distance(x.iat[0], x.iat[1])) #some function works with grouped text
     ]
 ).reset_index()

x1.merge(x2)

    audio  operator1  operator2  leven  text1  text2
0  audio1  operator1  operator2      1  text1  text2
1  audio2  operator3  operator4      1  text3  text4
2  audio3  operator5  operator6      1  text5  text6
Ryan Hunt
quelle
0

Diese Lösung funktioniert hervorragend, wenn Sie viele Spalten haben. Sie erweitert sie automatisch, sodass Sie sie nicht manuell auflisten müssen.

x = pd.DataFrame({
    'audio': ['audio1', 'audio1', 'audio2', 'audio2', 'audio3', 'audio3'],
    'text': ['text1', 'text2', 'text3', 'text4', 'text5', 'text6'],
    'login': ['operator1', 'operator2', 'operator3', 'operator4', 'operator5', 'operator6'] 
})


text = x.groupby(['audio']).agg(list)['text'].apply(pd.Series).rename(columns=lambda x: f'text{x+1}')

login = x.groupby(['audio']).agg(list)['login'].apply(pd.Series).rename(columns=lambda x: f'login{x+1}')

text['leven'] = df.apply(lambda x: Levenshtein.distance(x.text1, x.text2), axis=1) 

df = text.assign(**login)

        text1  text2  leven     login1     login2
audio                                            
audio1  text1  text2      1  operator1  operator2
audio2  text3  text4      1  operator3  operator4
audio3  text5  text6      1  operator5  operator6
Unterdrücker
quelle
0

Sie können Ihren aggAusdruck einfach folgendermaßen ändern :

x1 = x.groupby('audio').agg({'text':[
    ('text1', lambda x : x.iat[0]),
    ('text2', lambda x : x.iat[1])
    ('leven', lambda x: Levenshtein.distance(x.iat[0], x.iat[1])) #some function works with grouped text
    ],
    'login': [
    ('login1', lambda x : x.iat[0]),
    ('login2', lambda x : x.iat[1])]
    }
).droplevel(0,axis=1).reset_index()
Stepan
quelle