如何在Pandas DataFrame
索引上应用函数的最佳方式?
目前我正在使用这种冗长的方法:
pd.DataFrame({"Month": df.reset_index().Date.apply(foo)})
当Date
是索引名称,foo
是我正在应用的函数名称。
正如评论中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。
唯一将索引转换为Series的方法是从中创建一个Series。
pd.Series(df.index.map(str.lower))
Index
类现在是StringAccessorMixin
的子类,这意味着你可以按照以下方式执行上述操作:
df.index.str.lower()
这仍然会生成一个索引对象,而不是一个数据系列。
x[0]
和 x[1]
,则可以使用切片。 - Elliottdf.index.map(str.lower)
的简化写法。 - Zeroto_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
。
假设您想通过将函数“foo”应用于索引来在当前数据帧中创建一个列。您可以编写...
df['Month'] = df.index.map(foo)
如果您只想生成该系列,可以执行以下操作...
pd.Series({x: foo(x) for x in foo.index})
pd.Series(index.map(myfunc), name=index.name)
)。这也不能用于多重索引。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%的情况下都有效。
rename
函数有一个 level
参数(现在是这样吗?)。因此,这样可以消除歧义:df.rename(index=rename_dict0, level=0).rename(index=rename_dict1, level=1)
。 - Antony Hatchkins
df.index.map(foo)
能正常工作吗? - HYRYpd.Series(df.index).apply(foo)
。 - Roman Pekardf.index = df.index.map(foo)
。 - Ben