Применение функции в индексе DataFrame
Каков наилучший способ применения функции по индексу Pandas DataFrame
?
В настоящее время я использую этот подробный подход:
pd.DataFrame({"Month": df.reset_index().Date.apply(foo)})
где Date
- это имя индекса, а foo
- имя функции, которую я применяю.
Ответы
Ответ 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% времени.