为什么我的Pandas的“应用”功能不能引用多个列?[关闭]


239

当将多个列与以下数据框一起使用时,Pandas Apply函数存在一些问题

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 

1
尽量避免使用apply。如果不确定是否需要使用它,则可能不需要。我建议看看我什么时候应该在代码中使用pandas apply()?
cs95

这仅涉及引用数据框列的语法错误,以及为什么函数需要参数。至于第二个问题,该函数my_test(a)不知道df它是什么,因为它没有作为参数传入(除非df应该是一个全局变量,这将是可怕的做法)。您需要将函数中需要的所有值作为参数传递(最好按顺序),否则该函数如何知道从何df而来?另外,在充满全局变量的命名空间中进行编程也是一种不好的做法,您不会捕获到此类错误。
smci

Answers:


379

好像您忘记了''字符串。

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)

谢谢,您是对的,我忘记了“。但是,对于更复杂的功能,我仍然存在相同的问题。非常感谢您的帮助。谢谢
安迪

5
[53-54]之后的@Andy允许您应用更复杂的功能。
安迪·海登

@Andy您可以像In [53]那样定义复杂的函数。
WaitingKuo

所有适用策略的执行效果都一样吗?我是熊猫的新手,并且总是发现它的应用有点神秘,但是您在[53-54]中的策略对我来说很容易理解(并希望记住)……在一张大桌子上,它和其他应用形式一样快呈现?
whytheq '16

为什么创建一个单独的方法被认为更优雅-即使对于微小的方法也是如此。我从事python重大项目已有7年了,但是pythonista由于包括该观点在内的某些观点,我可能永远不会被认为是a 。
javadba

33

如果您只想计算(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

16
我知道,这只是一个例子,显示了我将函数应用于多个列的问题
Andy

18

假设我们要对DataFrame df的列“ a”和“ b”应用add5函数

def add5(x):
    return x+5

df[['a', 'b']].apply(add5)

尝试您的代码段时出现以下错误。TypeError :('必须是str,而不是int','发生在索引b')请您调查一下。
debaonline4u

数据框的b列是字符串类型或对象类型列,应为整数列,并添加数字。
Mir_Murtaza

更改仅在分配后才适用吗?
S.aad

11

以上所有建议均有效,但如果您希望提高计算效率,则应利用numpy向量运算(如此处所述)

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上测试)
stason

3

这与先前的解决方案相同,但是我已经在df.apply本身中定义了该函数:

df['Value'] = df.apply(lambda row: row['a']%row['c'], axis=1)

2

我已经比较了上面讨论的所有三个。

使用值

%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个)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.