为啥我的 Pandas 引用多个列的“应用”函数不起作用? [关闭]
Posted
技术标签:
【中文标题】为啥我的 Pandas 引用多个列的“应用”函数不起作用? [关闭]【英文标题】:Why isn't my Pandas 'apply' function referencing multiple columns working? [closed]为什么我的 Pandas 引用多个列的“应用”函数不起作用? [关闭] 【发布时间】:2013-04-27 13:13:46 【问题描述】:当使用具有以下数据框的多列时,我的 Pandas 应用功能存在一些问题
df = DataFrame ('a' : np.random.randn(6),
'b' : ['foo', 'bar'] * 3,
'c' : np.random.randn(6))
还有下面的函数
def my_test(a, b):
return a % b
当我尝试使用以下功能应用此功能时:
df['Value'] = df.apply(lambda row: my_test(row[a], row[c]), axis=1)
我收到错误消息:
NameError: ("global name 'a' is not defined", u'occurred at index 0')
我不明白这条消息,我正确定义了名称。
非常感谢您在此问题上的任何帮助
更新
感谢您的帮助。我确实在代码中犯了一些语法错误,索引应该放在''。但是我仍然使用更复杂的功能遇到同样的问题,例如:
def my_test(a):
cum_diff = 0
for ix in df.index():
cum_diff = cum_diff + (a - df['a'][ix])
return cum_diff
【问题讨论】:
尽量避免使用apply
。如果您不确定是否需要使用它,则可能不需要。我建议看看When should I ever want to use pandas apply() in my code?。
这只是关于引用数据框列的语法错误,以及为什么函数需要参数。至于你的第二个问题,函数my_test(a)
不知道df
是什么,因为它没有作为参数传入(除非df
应该是一个全局的,这将是一个糟糕的做法)。您需要将函数内部所需的所有值作为参数传递(最好按顺序),否则函数如何知道df
的来源?此外,在一个充斥着全局变量的命名空间中进行编程是一种不好的做法,你不会捕捉到这样的错误。
【参考方案1】:
我已经给出了上面讨论的所有三个的比较。
使用价值观
%timeit df['value'] = df['a'].values % df['c'].values
每个循环 139 µs ± 1.91 µs(7 次运行的平均值 ± 标准偏差,每次 10000 个循环)
没有价值观
%timeit df['value'] = df['a']%df['c']
每个循环 216 µs ± 1.86 µs(7 次运行的平均值 ± 标准偏差,每次 1000 个循环)
应用功能
%timeit df['Value'] = df.apply(lambda row: row['a']%row['c'], axis=1)
每个循环 474 µs ± 5.07 µs(7 次运行的平均值 ± 标准偏差,每次 1000 个循环)
【讨论】:
【参考方案2】:这与之前的解决方案相同,但我在 df.apply 本身中定义了函数:
df['Value'] = df.apply(lambda row: row['a']%row['c'], axis=1)
【讨论】:
【参考方案3】:以上所有建议都有效,但如果您希望计算效率更高,您应该利用 numpy 向量操作(as pointed out here)。
import pandas as pd
import numpy as np
df = pd.DataFrame ('a' : np.random.randn(6),
'b' : ['foo', 'bar'] * 3,
'c' : np.random.randn(6))
示例 1:循环使用 pandas.apply()
:
%%timeit
def my_test2(row):
return row['a'] % row['c']
df['Value'] = df.apply(my_test2, axis=1)
最慢的运行时间是最快的运行时间的 7.49 倍。这可以 表示正在缓存中间结果。 1000 个循环,最好的 3:每个循环 481 µs
示例 2:使用 pandas.apply()
进行矢量化:
%%timeit
df['a'] % df['c']
最慢的运行时间是最快的运行时间的 458.85 倍。这可以 表示正在缓存中间结果。 10000 个循环,最好的 3:每个循环 70.9 µs
示例 3:使用 numpy 数组进行矢量化:
%%timeit
df['a'].values % df['c'].values
最慢的运行时间是最快的运行时间的 7.98 倍。这可以 表示正在缓存中间结果。 100000 次循环,最佳 3:每个循环 6.39 µs
因此使用 numpy 数组进行矢量化将速度提高了近两个数量级。
【讨论】:
对于大数字,结果变化更大,例如用 10K 替换 6,我分别得到 248 ms、332 µs、263 µs。所以两个矢量化解决方案彼此更接近,但非矢量化解决方案慢了 1000 倍。 (在 python-3.7 上测试)【参考方案4】:假设我们要将函数 add5 应用于 DataFrame df 的“a”和“b”列
def add5(x):
return x+5
df[['a', 'b']].apply(add5)
【讨论】:
在尝试您的代码 sn-p 时出现以下错误。 TypeError: ('must be str, not int', 'occured at index b') 你能看看吗? 你的dataframe的b列是字符串类型或者对象类型的列,应该是整数列加上数字。 更改不是只在分配后应用吗?【参考方案5】:您似乎忘记了字符串的''
。
In [43]: df['Value'] = df.apply(lambda row: my_test(row['a'], row['c']), axis=1)
In [44]: df
Out[44]:
a b c Value
0 -1.674308 foo 0.343801 0.044698
1 -2.163236 bar -2.046438 -0.116798
2 -0.199115 foo -0.458050 -0.199115
3 0.918646 bar -0.007185 -0.001006
4 1.336830 foo 0.534292 0.268245
5 0.976844 bar -0.773630 -0.570417
顺便说一句,在我看来,以下方式更优雅:
In [53]: def my_test2(row):
....: return row['a'] % row['c']
....:
In [54]: df['Value'] = df.apply(my_test2, axis=1)
【讨论】:
谢谢,你说得对,我忘记了''。但是,对于更复杂的功能,我仍然有同样的问题。我非常感谢您的帮助。谢谢 @Andy 关注 [53-54] 允许您应用更复杂的功能。 @Andy 你可以像 In[53] 方式定义你的复杂函数。 所有应用策略的表现都一样吗?我是 pandas 的新手,总是觉得 apply 有点神秘,但你在 [53-54] 中的策略对我来说很容易理解(并希望记住)......在一张大桌子上它是否和其他形式的 apply 一样快介绍?axis=1
在这里很重要【参考方案6】:
如果只想计算(a列)%(b列),则不需要apply
,直接做即可:
In [7]: df['a'] % df['c']
Out[7]:
0 -1.132022
1 -0.939493
2 0.201931
3 0.511374
4 -0.694647
5 -0.023486
Name: a
【讨论】:
我知道,这只是一个例子来说明我在将函数应用于多列时遇到的问题以上是关于为啥我的 Pandas 引用多个列的“应用”函数不起作用? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章
pandas编写自定义函数计算多个数据列的加和(sum)使用groupby函数和apply函数聚合计算分组内多个数据列的加和
pandas使用stack函数map函数unstack函数以及字典同时替换dataframe多个数据列的内容
为啥我的应用程序不能以 pandas_udf 和 PySpark+Flask 开头?
将函数应用于 Pandas.DataFrame 中两列的每个组合的更好方法
pandas使用unique函数计算dataframe单个数据列中的独特值或者计算dataframe多个数据列的独特值(get unique values of column or columns)