Подтвердить что ты не робот

Применение функции в индексе DataFrame

Каков наилучший способ применения функции по индексу Pandas DataFrame? В настоящее время я использую этот подробный подход:

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

где Date - это имя индекса, а foo - имя функции, которую я применяю.

4b9b3361

Ответ 1

Как уже было предложено 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. Это связано с тем, что индексы dataframe основаны на массивах numpy, а не на Series.

Единственный способ сделать индекс в Серии - создать из него Серию.

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

Caveat

Класс Index теперь подклассифицирует StringAccessorMixin, что означает, что вы можете выполнить описанную выше операцию следующим образом

df.index.str.lower()

Это все еще создает объект Index, а не серию.

Ответ 2

Предполагая, что вы хотите сделать столбец в вашем текущем DataFrame, применив вашу функцию "foo" к индексу. Вы могли бы написать...

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

Чтобы генерировать серию в одиночку, вы могли бы сделать это...

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

Ответ 3

Многие ответы возвращают индекс как массив, который теряет информацию об имени индекса и т.д. (хотя вы могли бы сделать pd.Series(index.map(myfunc), name=index.name)). Он также не будет работать для MultiIndex.

Способ, которым я работал с этим, - использовать "rename":

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% времени.