python pandas:将带有参数的函数应用于系列
Posted
技术标签:
【中文标题】python pandas:将带有参数的函数应用于系列【英文标题】:python pandas: apply a function with arguments to a series 【发布时间】:2012-08-24 08:20:02 【问题描述】:我想将一个带参数的函数应用于 python pandas 中的系列:
x = my_series.apply(my_function, more_arguments_1)
y = my_series.apply(my_function, more_arguments_2)
...
documentation 描述了对 apply 方法的支持,但它不接受任何参数。是否有不同的方法可以接受参数?或者,我是否缺少一个简单的解决方法?
更新(2017 年 10 月): 请注意,由于最初提出此问题,pandas apply()
已更新以处理位置和关键字参数,上面的文档链接现在反映了这一点并显示了如何包括任一类型的参数。
【问题讨论】:
为什么不直接使用functools.partial
,或者starmap
?
见DataFrame.apply
docs和Series.apply
docs
【参考方案1】:
大部分内容都包含在其他答案中,想要重复您可能错过的内容,您需要在 args 元组中的参数后添加逗号,请参见以下示例:
df['some_column'].apply(function_name, args=(arg1 ,) #Here comma is necessary.
【讨论】:
【参考方案2】:#sample dataframe
import pandas as pd
df1=pd.DataFrame('a':[3,4,7],'b':[4,2,2])
#my function
def add_some(p,q,r):return p+q+r
df2=df1[["a","b"]].apply(add_some, args=(3,2))
print(df2)
_a b
0 8 9
1 9 7
2 12 7
【讨论】:
【参考方案3】:新版本的 pandas do 允许您传递额外的参数(请参阅 new documentation)。所以现在你可以这样做了:
my_series.apply(your_function, args=(2,3,4), extra_kw=1)
位置参数添加在序列元素之后。
对于旧版本的熊猫:
文档清楚地解释了这一点。 apply 方法接受一个 python 函数,该函数应该有一个参数。如果您想传递更多参数,您应该按照 Joel Cornett 在他的评论中的建议使用 functools.partial
。
一个例子:
>>> import functools
>>> import operator
>>> add_3 = functools.partial(operator.add,3)
>>> add_3(2)
5
>>> add_3(7)
10
您也可以使用partial
传递关键字参数。
另一种方法是创建一个 lambda:
my_series.apply((lambda x: your_func(a,b,c,d,...,x)))
但我认为使用partial
更好。
【讨论】:
对于 DataFrame 应用方法接受args
参数,这是一个包含附加位置参数的元组或 **kwds 用于命名的参数。我也为 Series.apply() github.com/pydata/pandas/issues/1829 创建了一个问题
功能已实现,将在即将发布的 pandas 中发布
这是一个不错的答案,但它的前 2/3 现在已经过时了。 IMO,只需作为新文档的链接以及如何与位置和/或关键字参数一起使用的简短示例,就可以很好地更新此答案。只是 FWIW 而不是对原始答案的批评,只会从更新 IMO 中受益,尤其是因为它是一个经常阅读的答案。
@watsonic 文档已经更新,点击旧链接可以看到当前文档,该文档现在很好地回答了这个问题。
注意:如果您传递单个字符串参数,例如'abc'
,则args=('abc')
将被评估为三个参数('a', 'b', 'c')
。为避免这种情况,您必须传递一个包含字符串的元组,为此,请包含一个尾随逗号:args=('abc',)
【参考方案4】:
您可以通过未命名的参数、作为元组传递给args
参数或通过kwds
内部捕获为字典的其他关键字参数将任意数量的参数传递给apply
正在调用的函数参数。
例如,让我们构建一个函数,它对 3 到 6 之间的值返回 True,否则返回 False。
s = pd.Series(np.random.randint(0,10, 10))
s
0 5
1 3
2 1
3 1
4 6
5 0
6 3
7 4
8 9
9 6
dtype: int64
s.apply(lambda x: x >= 3 and x <= 6)
0 True
1 True
2 False
3 False
4 True
5 False
6 True
7 True
8 False
9 True
dtype: bool
这个匿名函数不是很灵活。让我们创建一个带有两个参数的普通函数来控制我们想要的系列中的最小值和最大值。
def between(x, low, high):
return x >= low and x =< high
我们可以通过将未命名的参数传递给args
来复制第一个函数的输出:
s.apply(between, args=(3,6))
或者我们可以使用命名参数
s.apply(between, low=3, high=6)
甚至两者兼而有之
s.apply(between, args=(3,), high=6)
【讨论】:
【参考方案5】:Series.apply(func, convert_dtype=True, args=(), **kwds)
args : tuple
x = my_series.apply(my_function, args = (arg1,))
【讨论】:
谢谢!你能解释一下为什么 args = (arg1,) 在第一个参数之后需要一个逗号吗? @MishaTeplitskiy,您需要逗号才能让 Python 将括号的内容理解为长度为 1 的元组。 为func
输入参数怎么样。所以如果我想申请pd.Series.mean(axis=1)
,我该如何输入axis=1
?
附带说明,您还可以在不使用 参数的情况下添加关键字参数(例如:x = my_series.apply(my_function, keyword_arg=arg1),其中 步骤:
-
创建数据框
创建函数
在 apply 语句中使用函数的命名参数。
示例
x=pd.DataFrame([1,2,3,4])
def add(i1, i2):
return i1+i2
x.apply(add,i2=9)
此示例的结果是数据框中的每个数字都将添加到数字 9。
0
0 10
1 11
2 12
3 13
说明:
“add”函数有两个参数:i1,i2。第一个参数将是数据框中的值,第二个参数是我们传递给“应用”函数的任何值。在这种情况下,我们使用关键字参数“i2”将“9”传递给应用函数。
【讨论】:
正是我想要的。值得注意的是,这不需要创建自定义函数来处理系列(或 df)。完美! 剩下的唯一问题是:如何将关键字参数传递给 add(i1) 中的第一个 arg 并使用 i2 进行迭代? 我认为这是最好的答案 继@Connor 的评论之后,当必须指定第一个位置参数时,如何处理 2 个位置参数?以上是关于python pandas:将带有参数的函数应用于系列的主要内容,如果未能解决你的问题,请参考以下文章
使用带有参数的 Pandas groupby() + apply()
将函数应用于pandas Python中的每一行时出现数据转换错误