ottenere l'indice di una riga in una funzione di applicazione dei panda


121

Sto cercando di accedere all'indice di una riga in una funzione applicata a un intero DataFramein Panda. Ho qualcosa del genere:

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

e definirò una funzione che accede agli elementi con una data riga

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

Posso applicarlo in questo modo:

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

Eccezionale! E se volessi incorporare l'indice nella mia funzione? L'indice di una determinata riga in questo DataFrameprima di aggiungere dsarebbe Index([u'a', u'b', u'c', u'd'], dtype='object'), ma voglio lo 0 e 1. Quindi non posso semplicemente accedere row.index.

So che potrei creare una colonna temporanea nella tabella in cui memorizzo l'indice, ma mi chiedo se è memorizzato da qualche parte nell'oggetto riga.


1
A parte: c'è un motivo per cui devi usare apply? È molto più lento che eseguire operazioni vettorializzate sul frame stesso. (A volte applicare è il modo più semplice per fare qualcosa e le considerazioni sulle prestazioni sono spesso esagerate, ma per il tuo esempio particolare è altrettanto facile non usarlo.)
— DSM

1
@DSM in realtà sto chiamando un altro costruttore di oggetti per ogni riga utilizzando diversi elementi di riga. Volevo solo mettere insieme un esempio minimo per illustrare la domanda.
— Mike

Risposte:


148

Per accedere all'indice in questo caso si accede nameall'attributo:

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

Nota che se questo è davvero ciò che stai cercando di fare, ciò che segue funziona ed è molto più veloce:

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

MODIFICARE

Guardando questa domanda 3+ anni dopo, potresti semplicemente fare:

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

ma supponendo che non sia così banale, qualunque cosa tu rowFuncstia realmente facendo, dovresti cercare di usare le funzioni vettorizzate, e poi usarle contro l'indice 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

Sarebbe bello se namefosse una tupla con nome nel caso di a Multindex, in modo che un livello di indice specifico possa essere interrogato dal suo nome.
— Konstantin

18

O:

1. con row.nameall'interno del apply(..., axis=1)bando:

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

   a  b  c
x  1  2  3
y  4  5  6

df.apply(lambda row: row.name, axis=1)

x    x
y    y

2. con iterrows()(più lento)

DataFrame.iterrows () ti consente di scorrere su righe e accedere al loro indice:

for idx, row in df.iterrows():
    ...

2
e, se interessato, '' itertuples esegue generalmente molto meglio: stackoverflow.com/questions/24870953/...
— DPB

6

Per rispondere alla domanda originale: sì, puoi accedere al valore di indice di una riga in apply(). È disponibile sotto la chiave namee richiede che tu specifichi axis=1(perché lambda elabora le colonne di una riga e non le righe di una colonna).

Esempio di lavoro (panda 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

1
Funziona anche per i dataframe con MultiIndex: row.name diventa una tupla.
— Charles Fox
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.