2016-12-01 7 views
1

Ich habe zwei Datenrahmen. df1 sieht aus wie -Listenindex Außerhalb des Bereichs Fehler - Pandas

MovieName Actors 
lights out Maria Bello 
legend  Tom Hardy*Emily Browning*Christopher Eccleston*David Thewlis 

df2 sieht aus wie -

ActorName Gender 
Tom   male 
Emily  female 
Christopher male 

ich zwei Spalten in df1 hinzufügen möchten ‚female_actors‘ und ‚male_actors‘, die die Anzahl der weiblichen und männlichen Schauspieler in diesem speziellen Film enthält beziehungsweise. Ob ein Schauspieler männlich oder weiblich ist, basiert auf df2.

Hier ist, was ich tue -

def func(actors, gender): 
    actors = [act.split()[0] for act in actors.split('*')]  
    n_gender = df2.Gender[df2.Gender==gender][df2.ActorName.isin(actors)].count() 
    return n_gender 

df1['male_actors'] = df1.Actors.apply(lambda x: func(x, 'male')) 
df1['female_actors'] = df1.Actors.apply(lambda x: func(x, 'female')) 

Dieser Code gibt mir die Liste Indexfehler außerhalb des zulässigen Bereichs.

Bitte beachten Sie, dass -

Wenn bestimmte Namen nicht in gender.csv ist, kann es nicht in der Gesamt zählen. Wenn nur ein Akteur in einem Film vorhanden ist und in gender.csv nicht vorhanden ist, sollte die Anzahl null sein.

Ergebnis sollte -

MovieName Actors  male_actors female_actors 
lights out Maria Bello 0    0 
legend  Tom Hardy*Emily Browning*Christopher Eccleston*David Thewlis 2 1 

Fühlen Sie sich frei einen anderen Ansatz vorschlagen.

+0

Nur Platz in Ihrem Code, wo eine Liste indiziert wird, ist an der 'act.split() [0]', ist es möglich, dass in einigen Fällen die 'Schauspieler' Feld ist leer? – sirfz

+0

@sirfz Ich habe alle leeren Zeilen entfernt. Es läuft jetzt. Aber was denkst du ist das Problem, dass es nur eine maximale Anzahl von 1 identifiziert, selbst wenn 20 Schauspieler erwähnt werden. Liest es automatisch nur eine bestimmte Zeilenlänge? – ComplexData

Antwort

2

Wie wäre es damit?

df1['Male'] = df1.Actors.apply(lambda x: len(pd.concat([df2[(df2.ActorName == name) & (df2.Gender == 'male')] for name in x.split('*')]))) 
df1['Female'] = df1.Actors.apply(lambda x: len(pd.concat([df2[(df2.ActorName == name) & (df2.Gender == 'female')] for name in x.split('*')]))) 
+0

Dies muss bearbeitet werden, wenn Ihre Akteurennamen in 'df2' z. "Tom" - wie geschrieben - statt "Tom Hardy". Wenn Sie nur die Vornamen haben, können Sie '(df2.ActorName == Name)' durch '(df2.ActorName == name.split() [0])' – AlexG

+0

ersetzen. Ich mache den gleichen Prozess für andere Felder wie Directors , Writers usw., und ich bekomme einen Index außerhalb des Bereichs Fehler. Können Sie eine mögliche Lösung vorschlagen? – ComplexData

+0

Von dem, was ich sagen kann, würde dies nur geschehen, wenn Sie die '(df2.ActorName == name.split() [0])' Änderung, die ich vorgeschlagen habe, enthalten, haben Sie das hinzugefügt? Versuchen Sie, 'if name' in das Listenverständnis einzubeziehen, z. '[df2 [(df2.ActorName == name.split() [0]) & (df2.Gender == 'weiblich')] für den Namen in x.split ('*') wenn name] ' – AlexG

1

Verwendung str und join

d2 = df2.set_index('ActorName') 
d1 = df1.set_index('MovieName') 

Methode 1
split

d1.join(d1.Actors.str.split('*', expand=True).stack() \ 
    .str.split(expand=True)[0].map(d2.Gender) \ 
    .groupby(level='MovieName') \ 
    .value_counts().unstack()).fillna(0).reset_index() 

metho d 2
extractall

d1.join(d1.Actors.str.extractall('((?P<first>[^*]+)\s+(?P<last>[^*]+))') \ 
    ['first'].map(d2.Gender).groupby(level='MovieName') \ 
    .value_counts().unstack()).fillna(0).reset_index() 

enter image description here

Verwandte Themen