web-dev-qa-db-fra.com

obtenir l'index d'une ligne dans une fonction pandas apply

J'essaie d'accéder à l'index d'une ligne dans une fonction appliquée à l'ensemble d'un DataFrame dans Pandas. J'ai quelque chose comme ça:

df = pandas.DataFrame([[1,2,3],[4,5,6]], columns=['a','b','c'])
>>> df
   a  b  c
0  1  2  3
1  4  5  6

et je vais définir une fonction qui accède aux éléments avec une ligne donnée

def rowFunc(row):
    return row['a'] + row['b'] * row['c']

Je peux l'appliquer comme suit:

df['d'] = df.apply(rowFunc, axis=1)
>>> df
   a  b  c   d
0  1  2  3   7
1  4  5  6  34

Impressionnant! Et maintenant, si je veux incorporer l'index dans ma fonction? L'index d'une ligne donnée dans ce DataFrame avant d'ajouter d serait Index([u'a', u'b', u'c', u'd'], dtype='object'), mais je veux les 0 et 1. Je ne peux donc pas simplement accéder à row.index.

Je sais que je pourrais créer une colonne temporaire dans la table où je stocke l’index, mais je me demande s’il est écrit quelque part dans l’objet row.

85
Mike

Pour accéder à l'index dans ce cas, vous accédez à l'attribut name:

In [182]:

df = pd.DataFrame([[1,2,3],[4,5,6]], columns=['a','b','c'])
def rowFunc(row):
    return row['a'] + row['b'] * row['c']

def rowIndex(row):
    return row.name
df['d'] = df.apply(rowFunc, axis=1)
df['rowIndex'] = df.apply(rowIndex, axis=1)
df
Out[182]:
   a  b  c   d  rowIndex
0  1  2  3   7         0
1  4  5  6  34         1

Notez que si c'est vraiment ce que vous essayez de faire, cela fonctionne et est beaucoup plus rapide:

In [198]:

df['d'] = df['a'] + df['b'] * df['c']
df
Out[198]:
   a  b  c   d
0  1  2  3   7
1  4  5  6  34

In [199]:

%timeit df['a'] + df['b'] * df['c']
%timeit df.apply(rowIndex, axis=1)
10000 loops, best of 3: 163 µs per loop
1000 loops, best of 3: 286 µs per loop

EDIT

En regardant cette question 3 ans et plus plus tard, vous pourriez simplement faire:

In[15]:
df['d'],df['rowIndex'] = df['a'] + df['b'] * df['c'], df.index
df

Out[15]: 
   a  b  c   d  rowIndex
0  1  2  3   7         0
1  4  5  6  34         1

mais en supposant que ce ne soit pas aussi trivial, peu importe ce que votre rowFunc fait réellement, vous devriez chercher à utiliser les fonctions vectorisées, puis à les utiliser contre l'index df:

In[16]:
df['newCol'] = df['a'] + df['b'] + df['c'] + df.index
df

Out[16]: 
   a  b  c   d  rowIndex  newCol
0  1  2  3   7         0       6
1  4  5  6  34         1      16
107
EdChum

apply() n'est pas le droïde que vous recherchez.

DataFrame.iterrows () vous permet de parcourir des lignes et d'accéder à leur nom:

for name, row in df.iterrows():
    ...
6
smci

Pour répondre à la question initiale: oui, vous pouvez accéder à la valeur d'index d'une ligne dans apply(). Il est disponible sous la clé name et nécessite que vous spécifiez axis=1 (car lambda traite les colonnes d’une ligne et non les lignes d’une colonne).

Exemple de travail (pandas 0.23.4):

>>> import pandas as pd
>>> df = pd.DataFrame([[1,2,3],[4,5,6]], columns=['a','b','c'])
>>> df.set_index('a', inplace=True)
>>> df
   b  c
a      
1  2  3
4  5  6
>>> df['index_x10'] = df.apply(lambda row: 10*row.name, axis=1)
>>> df
   b  c  index_x10
a                 
1  2  3         10
4  5  6         40
3
Freek Wiekmeijer