Pandas - 使用apply为浮点索引数据框创建新列

3 投票
1 回答
4355 浏览
提问于 2025-04-20 09:44

我正在使用 pandas 13.0,想通过 apply() 方法和一个叫 foo() 的函数来创建一个新列。

我的数据框(dataframe)如下:

df = pandas.DataFrame({
         'a':[ 0.0,  0.1,  0.2,  0.3], 
         'b':[10.0, 20.0, 30.0, 40.0], 
         'c':[ 1.0,  2.0,  3.0,  4.0]
     })

df.set_index(df['a'], inplace=True)

所以我的数据框是:

in: print df

out:
           a    b     c
      a
      0.0  0.0  10.0  1.0
      0.1  0.1  20.0  2.0
      0.2  0.2  30.0  3.0
      0.3  0.3  40.0  4.0 

我的函数是:

def foo(arg1, arg2):
    return arg1*arg2

现在我想用 foo() 创建一个名为 'd' 的列;

df['d'] = df.apply(foo(df['b'], df['c']), axis=1)

但是我遇到了以下错误:

TypeError: ("'Series' object is not callable", u'occurred at index 0.0')

我该如何使用 pandas.apply() 和 foo(),当索引是浮点数时?

谢谢

1 个回答

5

这里的问题是,你试图按行处理数据,但你传递的是系列作为参数,这样做是不对的。你可以这样做:

In [7]:

df['d'] = df.apply(lambda row: foo(row['b'], row['c']), axis=1)
df
Out[7]:
       a   b  c    d
a                   
0.0  0.0  10  1   10
0.1  0.1  20  2   40
0.2  0.2  30  3   90
0.3  0.3  40  4  160

更好的方法是直接调用你的函数:

In [8]:

df['d'] = foo(df['b'], df['c'])
df
Out[8]:
       a   b  c    d
a                   
0.0  0.0  10  1   10
0.1  0.1  20  2   40
0.2  0.2  30  3   90
0.3  0.3  40  4  160

上面这种方法的好处是它是向量化的,这意味着它会对整个系列进行操作,而不是一行一行地处理。

In [15]:

%timeit df['d'] = df.apply(lambda row: foo(row['b'], row['c']), axis=1)
%timeit df['d'] = foo(df['b'], df['c'])
1000 loops, best of 3: 270 µs per loop
1000 loops, best of 3: 214 µs per loop

这里没什么太大区别,现在我们来对比一下一个有40万行的数据框:

In [18]:

%timeit df['d'] = df.apply(lambda row: foo(row['b'], row['c']), axis=1)
%timeit df['d'] = foo(df['b'], df['c'])
1 loops, best of 3: 5.84 s per loop
100 loops, best of 3: 8.68 ms per loop

所以你可以看到,这样做的速度提升大约是672倍。

撰写回答