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.
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
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():
...
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