web-dev-qa-db-fra.com

pandas python - applique une fonction avec deux arguments aux colonnes

Pouvez-vous faire fonctionner un pandas python avec des valeurs dans deux colonnes différentes comme arguments?

J'ai une fonction qui retourne un 1 si deux colonnes ont des valeurs dans la même plage. sinon, il retourne 0:

def segmentMatch(RealTime, ResponseTime):
    if RealTime <= 566 and ResponseTime <= 566:
        matchVar = 1
    Elif 566 < RealTime <= 1132 and 566 < ResponseTime <= 1132:
        matchVar = 1
    Elif 1132 < RealTime <= 1698 and 1132 < ResponseTime <= 1698:
        matchVar = 1
    else:
        matchVar = 0
    return matchVar

Je veux que le premier argument, RealTime, soit une colonne de mon cadre de données, de sorte que la fonction prenne la valeur de chaque ligne de cette colonne. par exemple. RealTime est df['TimeCol'] et le deuxième argument est df ['ResponseCol'] `. Et j'aimerais que le résultat soit une nouvelle colonne dans le cadre de données. Je suis tombé sur plusieursthreads qui ont répondu à une question similaire, mais il semble que ces arguments étaient des variables et non des valeurs dans les lignes du cadre de données.

J'ai essayé ce qui suit mais cela n'a pas fonctionné:

df['NewCol'] = df.apply(segmentMatch, args=(df['TimeCol'], df['ResponseCol']), axis=1)
7
Maria

Pourquoi ne pas simplement faire ça?

df['NewCol'] = df.apply(lambda x: segmentMatch(x['TimeCol'], x['ResponseCol']), axis=1)

Plutôt que d'essayer de passer la colonne en tant qu'argument, comme dans votre exemple, nous passons simplement les entrées appropriées dans chaque ligne en tant qu'argument et stockons le résultat dans 'NewCol'.

14
N. Wouda

Vous n'avez pas vraiment besoin d'une fonction lambda si vous définissez la fonction à l'extérieur:

def segmentMatch(vec):
    RealTime = vec[0]
    ResponseTime = vec[1]
    if RealTime <= 566 and ResponseTime <= 566:
        matchVar = 1
    Elif 566 < RealTime <= 1132 and 566 < ResponseTime <= 1132:
        matchVar = 1
    Elif 1132 < RealTime <= 1698 and 1132 < ResponseTime <= 1698:
        matchVar = 1
    else:
        matchVar = 0
    return matchVar

df['NewCol'] = df[['TimeCol', 'ResponseCol']].apply(segmentMatch, axis=1)

Si "segmentMatch" devait renvoyer un vecteur de 2 valeurs, vous pouvez procéder comme suit:

def segmentMatch(vec):
    ......
    return pd.Series((matchVar1, matchVar2)) 

df[['NewCol', 'NewCol2']] = df[['TimeCol','ResponseCol']].apply(segmentMatch, axis=1)
2
rahul