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.