Python 当前面的值很重要时,如何使用“apply()”或其他矢量化方法

Python 当前面的值很重要时,如何使用“apply()”或其他矢量化方法,python,python-3.x,pandas,Python,Python 3.x,Pandas,假设我有一个如下形式的数据帧,其中第一列是一个随机数,其他列将基于前一列中的值 为了便于使用,假设我希望每个数字都是前一个数字的平方。所以它看起来像下图 我知道我可以编写一个非常简单的循环来实现这一点,但我也知道循环在python/pandas中通常不是最有效的。如何使用apply()或rolling\u apply()?或者,以其他方式可以更有效地完成 我的(失败)尝试如下: In [12]: a = pandas.DataFrame({0:[1,2,3,4,5],1:0,2:0,3:0}

假设我有一个如下形式的数据帧,其中第一列是一个随机数,其他列将基于前一列中的值

为了便于使用,假设我希望每个数字都是前一个数字的平方。所以它看起来像下图

我知道我可以编写一个非常简单的循环来实现这一点,但我也知道循环在python/pandas中通常不是最有效的。如何使用
apply()
rolling\u 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]: 
[12]中的
a=pandas.DataFrame({0:[1,2,3,4,5],1:0,2:0,3:0})
在[13]中:a
出[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
在[14]中:a=a.apply(λx:x**2)
在[15]中:a
出[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
[16]中:a=pandas.DataFrame({0:[1,2,3,4,5],1:0,2:0,3:0})
在[17]中:熊猫。滚动应用(a,1,λx:x**2)
C:\WinPython64bit\python-3.5.2.amd64\lib\site packages\spyderlib\widgets\externalshell\start\u ipython\u kernel.py:1:FutureWarning:pd.rolling\u apply不推荐用于DataFrame,并将在将来的版本中删除,替换为
DataFrame.rolling(center=False,window=1).apply(args=,kwargs=,func=)
#-*-编码:utf-8-*-
出[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
[18]中:a=pandas.DataFrame({0:[1,2,3,4,5],1:0,2:0,3:0})
在[19]中:a=a[:-1]**2
在[20]中:a
出[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
在[21]中:
因此,我的问题主要是如何在数据帧计算中引用前面的列值

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

不幸的是,据我所知,没有一种没有循环的方法。但是,您不必遍历每个值,只需遍历每个列。您只需在上一列上调用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)

你所描述的是一个递归关系,我认为目前没有任何非循环的方法可以做到这一点。像
apply
rolling\u apply
这样的事情仍然依赖于在开始之前获得所有需要的数据,并在结束时一次输出所有结果数据。也就是说,它们不允许您使用同一系列的早期值计算下一个值。见及


在实际操作中,例如,您只需要填写三列,因此执行三次循环(如其他一些答案所示)可能不会对性能造成重大影响。

在这种特殊情况下,我们知道关于列的这一点

  • 0
    将成为
    1
  • 1
    将是列
    0
    中的任何一个,与
    2
  • 2
    将是列
    1
    中的所有内容,其作用是
    2
    。。。
    • 或者将是列
      0
      中的任何内容,以
      4
  • 3
    将是
    2
    列中的所有内容,其作用是
    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]])
将其包装在一个漂亮的数据框中

pd.DataFrame(
    np.power(df.values[:, [0]], np.power(2, np.arange(4))),
    df.index, df.columns)

   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

a[1]=a[0]。应用(lambda x:x**2),非常感谢您的回复。我的实际数据帧要大得多,并且包含一些逻辑。这只是一个简单的例子,从效率的角度来学习如何最好地实现这一点。这些链接很有帮助。我真的很喜欢这种方法,这当然回答了我的问题。然而,我接受了另一个答案,因为我的问题是广义的。“我应该想到有一种更专业的方法来解决我的具体问题。”凯尔说了几点。第一:知道你可以接受另一个答案,如果你发现它比当前接受的答案更合适的话。事实上,这是受到鼓励的。我的回答中有不少没有被接受,我对此没有意见。第二:有时更难的问题需要更多的时间来回答。如果你想要一个有挑战性的问题的高质量答案,请耐心等待。没有必要急于接受答案。你也可以直截了当地回答那些已经回答了你正在等待的问题的人。第三:我不太关心15个代表分数,更关心什么是对的。@Kyle说了这么多。我完全同意凯尔的回答。其他人会根据自己的意愿投赞成票或反对票。:-)我喜欢这个。又好又简单。我上一次尝试使用完整循环(以及使用附加逻辑的完整数据源,并应用scipy.fv())花费了2分钟,这种方法花费了不到一秒钟的时间。我觉得自己很愚蠢:)。