отримання індексу рядка в застосуванні функції панди


121

Я намагаюся отримати доступ до індексу рядка у функції, застосованій у цілому DataFrameв Pandas. У мене є щось подібне:

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

і я визначу функцію, яка отримує доступ до елементів із заданим рядком

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

Я можу це застосувати так:

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

Дивовижно! Що робити, якщо я хочу включити індекс у свою функцію? Індекс будь-якого даного рядка в цьомуDataFrame перед додаванням dбуде Index([u'a', u'b', u'c', u'd'], dtype='object'), але я хочу 0 і 1. Тому я не можу просто отримати доступ row.index.

Я знаю, що міг би створити тимчасовий стовпець у таблиці, де я зберігаю індекс, але мені цікаво, чи він десь зберігається в рядковому об’єкті.


1
Убік: чи є причина, яку потрібно використовувати apply? Це набагато повільніше, ніж виконувати векторизовані ОПС на самому кадрі. (Іноді застосовувати - це найпростіший спосіб зробити щось, а міркування щодо ефективності часто перебільшені, але для вашого конкретного прикладу це так само просто не використовувати.)
DSM

1
@DSM насправді я називаю інший конструктор об'єктів для кожного рядка, використовуючи різні елементи рядка. Я просто хотів скласти мінімальний приклад разом, щоб проілюструвати питання.
Майк

Відповіді:


148

Для доступу до індексу в цьому випадку ви отримуєте доступ до 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

Зауважте, що якщо це дійсно те, що ви намагаєтеся зробити, то наступне працює і набагато швидше:

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

Дивлячись на це запитання через 3 роки, ви можете просто зробити:

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

але якщо припустити, що це не так тривіально, як це, що б ви rowFuncнасправді не робили, вам слід поглянути на використання векторизованих функцій, а потім використовувати їх проти індексу 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

Було б добре, якби nameбуло названо кортеж у випадку а Multindex, щоб певний рівень індексу можна було запитати за його назвою.
Костянтин

18

Або:

1. з row.nameвнутрішнім apply(..., axis=1)викликом:

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. з iterrows()(повільніше)

DataFrame.iterrow () дозволяє переглядати рядки та отримувати доступ до їх індексу:

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

2
і, якщо стосується, «itertuples» зазвичай виконує набагато краще: stackoverflow.com/questions/24870953 / ...
DPb

6

Щоб відповісти на початкове запитання: так, ви можете отримати доступ до значення індексу рядка в apply(). Він доступний під ключем nameі вимагає вказатиaxis=1 (оскільки лямбда обробляє стовпці рядка, а не рядки стовпця).

Приклад роботи (панди 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
Також працює для фреймів даних з MultiIndex: row.name стає кортежем.
Чарльз Фокс
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.