当前一个值很重要时,如何使用`apply()`或其他矢量化方法

时间:2017-03-23 18:15:17

标签: python python-3.x pandas

假设我有一个以下形式的DataFrame,其中第一列是随机数,其他列将基于上一列中的值。

enter image description here

为了便于使用,假设我希望每个数字都是前一个数字。所以看起来如下所示。

enter image description here

我知道我可以写一个非常简单的循环来做这个,但我也知道循环在python / pandas中通常不是最有效的。如何使用apply()rolling_apply()完成此操作?或者,否则更有效率地完成?

我的(失败)尝试如下:

In [12]: a = pandas.DataFrame({0:[1,2,3,4,5],1:0,2:0,3:0})

In [13]: a
Out[13]: 
   0  1  2  3
0  1  0  0  0
1  2  0  0  0
2  3  0  0  0
3  4  0  0  0
4  5  0  0  0

In [14]: a = a.apply(lambda x: x**2)

In [15]: a
Out[15]: 
    0  1  2  3
0   1  0  0  0
1   4  0  0  0
2   9  0  0  0
3  16  0  0  0
4  25  0  0  0


In [16]: a = pandas.DataFrame({0:[1,2,3,4,5],1:0,2:0,3:0})

In [17]: pandas.rolling_apply(a,1,lambda x: x**2)
C:\WinPython64bit\python-3.5.2.amd64\lib\site-packages\spyderlib\widgets\externalshell\start_ipython_kernel.py:1: FutureWarning: pd.rolling_apply is deprecated for DataFrame and will be removed in a future version, replace with 
        DataFrame.rolling(center=False,window=1).apply(args=<tuple>,kwargs=<dict>,func=<function>)
  # -*- coding: utf-8 -*-
Out[17]: 
      0    1    2    3
0   1.0  0.0  0.0  0.0
1   4.0  0.0  0.0  0.0
2   9.0  0.0  0.0  0.0
3  16.0  0.0  0.0  0.0
4  25.0  0.0  0.0  0.0

In [18]: a = pandas.DataFrame({0:[1,2,3,4,5],1:0,2:0,3:0})

In [19]: a = a[:-1]**2

In [20]: a
Out[20]: 
    0  1  2  3
0   1  0  0  0
1   4  0  0  0
2   9  0  0  0
3  16  0  0  0

In [21]: 

所以,我的问题主要是如何在我的DataFrame计算中引用前一个列值。

4 个答案:

答案 0 :(得分:4)

您所描述的是递归关系,我认为目前没有任何非循环方式可以做到这一点。像applyrolling_apply之类的东西仍然依赖于在开始之前获得所有需要的数据,并在结束时立即输出所有结果数据。也就是说,它们不允许您使用同一系列的早期值计算下一个值。请参阅this questionthis one以及this pandas issue

实际上,对于您的示例,您只需要填写三列,因此执行三遍循环(如其他一些答案中所示)可能不会成为主要的性能影响。

答案 1 :(得分:3)

a[1] = a[0].apply(lambda x: x**2)
a[2] = a[1].apply(lambda x: x**2)
a[3] = a[2].apply(lambda x: x**2)

会给你

    0   1   2   3
0   1   1   1   1
1   2   4   16  256
2   3   9   81  6561
3   4   16  256 65536
4   5   25  625 390625

答案 2 :(得分:3)

不幸的是,据我所知,没有办法没有循环。但是,您不必遍历每个值,只需遍历每一列。您只需在上一列上调用apply并将下一列设置为返回值:

a = pd.DataFrame({0:[1,2,3,4,5],1:0,2:0,3:0})

for i in range(3):
    a[i+1] = a[i].apply(lambda x: x**2)

答案 3 :(得分:3)

在这种特殊情况下,我们知道有关列的信息

  • Proposition将成为0
  • 的强大力量
  • 1将成为第1栏中0
  • 的力量
  • 2将成为21的强大功能......
    • 或将成为2列中0
    • 的力量
  • 4将成为32的强大功能......
    • 或将成为2列中1 ...
    • 的强大功能
    • 或将成为4列中0
    • 的力量

因此我们确实可以使用

对您的示例进行矢量化
8

将其包装在漂亮的数据框中

np.power(df.values[:, [0]], np.power(2, np.arange(4)))

array([[     1,      1,      1,      1],
       [     2,      4,     16,    256],
       [     3,      9,     81,   6561],
       [     4,     16,    256,  65536],
       [     5,     25,    625, 390625]])