Застосувати функцію до індексу DataFrame


84

Який найкращий спосіб застосувати функцію до індексу Панд DataFrame? В даний час я використовую такий багатослівний підхід:

pd.DataFrame({"Month": df.reset_index().Date.apply(foo)})

де Date- це ім'я індексу і foo- це назва функції, яку я застосовую.


6
робить df.index.map(foo)роботу?
HYRY

1
Це "працює", але повертає масив numpy, а не серію Pandas.
Алекс Ротберг,

1
яка ваша кінцева мета? Ви можете передати масив конструктору DataFrame. Або зробіть щось на кшталтpd.Series(df.index).apply(foo)
Роман Пекар

Це повністю залежить від функції ...
Енді Хейден,

1
Виходячи з @HYRY, якщо ви просто хочете змінити індекс існуючого DataFrame, який ви можете зробитиdf.index = df.index.map(foo)
Бен

Відповіді:


99

Як вже пропонував HYRY у коментарях, сюди слід зайти Series.map . Просто встановіть індекс на отриманий ряд.

Простий приклад:

df = pd.DataFrame({'d': [1, 2, 3]}, index=['FOO', 'BAR', 'BAZ'])
df
        d
FOO     1
BAR     2
BAZ     3

df.index = df.index.map(str.lower)
df
        d
foo     1
bar     2
baz     3

Індекс! = Серія

Як зазначає @OP. df.index.map(str.lower)виклик повертає Numpy масив. Це тому, що індекси фреймів даних базуються на масивах numpy, а не на Series.

Єдиний спосіб перетворення індексу на Серію - це створення Серії з неї.

pd.Series(df.index.map(str.lower))

Застереження

Тепер Indexклас підкласує StringAccessorMixin, що означає, що описану операцію можна виконати наступним чином

df.index.str.lower()

Це все одно створює об’єкт Index, а не Series.


1
З мультиіндекс, ви можете використовувати нарізку , якщо ви хочете використовувати обидва пункт у вашій функції, наприклад , x[0]і x[1].
Елліот

3
Трохи коротший шляхdf.index.map(str.lower)
нуль

1
@JohnGalt Дякуємо, що вказали на це. Це не тільки коротше, але і швидше, оскільки str.lower - це скомпільована функція cython, а лямбда-функція, яку я писав, - ні.
firelynx

12

Якщо припустити, що ви хочете зробити стовпець у поточному DataFrame, застосувавши до індексу свою функцію "foo". Ви можете написати ...

df['Month'] = df.index.map(foo)

Щоб генерувати серію самостійно, ви можете замість цього зробити ...

pd.Series({x: foo(x) for x in foo.index})

1
Дуже не рекомендується використовувати для циклів у ехо-системі pandas / numpy. Це дуже неефективна пам’ять і легко виходить з ладу з більшими наборами даних.
firelynx

3

Багато відповідей повертають Індекс як масив, який втрачає інформацію про ім'я індексу тощо (хоча ви могли б це зробити pd.Series(index.map(myfunc), name=index.name)). Це також не буде працювати для MultiIndex.

Я працював із цим, використовуючи "перейменувати":

mix = pd.MultiIndex.from_tuples([[1, 'hi'], [2, 'there'], [3, 'dude']], names=['num', 'name'])
data = np.random.randn(3)
df = pd.Series(data, index=mix)
print(df)
num  name 
1    hi       1.249914
2    there   -0.414358
3    dude     0.987852
dtype: float64

# Define a few dictionaries to denote the mapping
rename_dict = {i: i*100 for i in df.index.get_level_values('num')}
rename_dict.update({i: i+'_yeah!' for i in df.index.get_level_values('name')})
df = df.rename(index=rename_dict)
print(df)
num  name       
100  hi_yeah!       1.249914
200  there_yeah!   -0.414358
300  dude_yeah!     0.987852
dtype: float64

Єдина хитрість із цим полягає в тому, що у вашому індексі повинні бути унікальні мітки ч / б різних рівнів мультиіндексу, але, можливо, хтось розумніший за мене знає, як це обійти. Для моїх цілей це працює в 95% випадків.


3

Ви завжди можете перетворити індекс, використовуючи його to_series()метод, а потім або applyабо map, відповідно до ваших уподобань / потреб.

ret = df.index.map(foo)                # Returns pd.Index
ret = df.index.to_series().map(foo)    # Returns pd.Series
ret = df.index.to_series().apply(foo)  # Returns pd.Series

Все вищезазначене можна призначити безпосередньо до нового або існуючого стовпця df:

df["column"] = ret

Просто для повноти: pd.Index.map, pd.Series.mapі pd.Series.applyвсі працюють поелементно. Я часто використовую mapдля пошуку пошуки, представлені dictsабо pd.Series. applyє більш загальним, оскільки ви можете передавати будь-яку функцію разом із додатковими argsабо kwargs. Відмінності між applyта mapобговорюються далі в цій темі SO . Не знаю, чому pd.Index.applyце опустили.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.