mendapatkan indeks baris dalam fungsi pandas apply

121

Saya mencoba mengakses indeks baris dalam fungsi yang diterapkan di seluruh DataFramePandas. Saya punya sesuatu seperti ini:

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

dan saya akan mendefinisikan fungsi yang mengakses elemen dengan baris tertentu

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

Saya bisa menerapkannya seperti ini:

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

Hebat! Sekarang bagaimana jika saya ingin memasukkan indeks ke dalam fungsi saya? Indeks dari setiap baris yang diberikan DataFramesebelum menambahkan dadalah Index([u'a', u'b', u'c', u'd'], dtype='object'), tetapi saya ingin 0 dan 1. Jadi saya tidak bisa begitu saja mengaksesrow.index .

Saya tahu saya bisa membuat kolom sementara di tabel tempat saya menyimpan indeks, tapi saya bertanya-tanya apakah itu disimpan di objek baris di suatu tempat.

Mike
sumber
1
Selain: apakah ada alasan Anda perlu menggunakan apply? Ini jauh lebih lambat daripada melakukan operasi vektor pada frame itu sendiri. (Kadang-kadang menerapkan adalah cara termudah untuk melakukan sesuatu, dan pertimbangan kinerja sering dilebih-lebihkan, tetapi untuk contoh khusus Anda, semudah itu untuk tidak menggunakannya.)
DSM
1
@DSM pada kenyataannya saya memanggil konstruktor objek lain untuk setiap baris menggunakan elemen baris yang berbeda. Saya hanya ingin memberikan contoh minimal untuk mengilustrasikan pertanyaan tersebut.
Mike

Jawaban:

148

Untuk mengakses indeks dalam hal ini Anda mengakses nameatribut:

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

Perhatikan bahwa jika ini benar-benar yang Anda coba lakukan, berikut ini berfungsi dan jauh lebih cepat:

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

Melihat pertanyaan ini 3+ tahun kemudian, Anda dapat melakukan:

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

tetapi dengan asumsi ini tidak sepele seperti ini, apa pun rowFuncyang sebenarnya Anda lakukan, Anda harus menggunakan fungsi vektorisasi, lalu menggunakannya pada indeks 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
EdChum
sumber
Akan lebih baik jika nameakan menjadi tupel bernama dalam kasus a Multindex, sehingga tingkat indeks tertentu dapat ditanyakan oleh namanya.
Konstantin
18

Antara:

1. dengan row.namedalam apply(..., axis=1)panggilan:

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. dengan iterrows()(lebih lambat)

DataFrame.iterrows () memungkinkan Anda melakukan iterasi pada baris, dan mengakses indeksnya:

for idx, row in df.iterrows():
    ...
smci
sumber
2
dan, jika khawatir, 'itertuples' umumnya berkinerja jauh lebih baik: stackoverflow.com/questions/24870953/…
dpb
6

Untuk menjawab pertanyaan awal: ya, Anda dapat mengakses nilai indeks baris dalam apply(). Ini tersedia di bawah kunci namedan mengharuskan Anda menentukan axis=1(karena lambda memproses kolom dari sebuah baris dan bukan baris dari sebuah kolom).

Contoh kerja (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
Freek Wiekmeijer
sumber
1
Juga berfungsi untuk kerangka data dengan MultiIndex: row.name menjadi tuple.
Charles Fox