python - 在 Pandas DataFrame 上对迭代函数进行矢量化
问题描述
我有一个数据框,其中第一行是初始条件。
df = pd.DataFrame({"Year": np.arange(4),
"Pop": [0.4] + [np.nan]* 3})
和一个函数f(x,r) = r*x*(1-x)
,其中r = 2
是一个常数和0 <= x <= 1
。
我想通过将函数Pop
逐行迭代地应用于列来生成以下数据框。IE,df.Pop[i] = f(df.Pop[i-1], r=2)
df = pd.DataFrame({"Year": np.arange(4),
"Pop": [0.4, 0.48, 4992, 0.49999872]})
问题:是否有可能以矢量化的方式做到这一点?
我可以通过使用循环为 x 和 y 值构建列表来实现所需的结果,但这不是矢量化的。
我也试过这个,但所有nan
地方都充满了0.48
.
df.loc[1:, "Pop"] = R * df.Pop[:-1] * (1 - df.Pop[:-1])
解决方案
以矢量化方式执行此操作是不可能的。
根据定义,向量化利用并行处理来减少执行时间。但是您问题中所需的值必须按顺序计算,而不是并行计算。有关详细说明,请参阅此答案。df.expanding (2).apply(f)和df.rolling(2).apply(f)之类的东西不起作用。
然而,获得更高的效率是可能的。您可以使用生成器进行迭代。这是实现迭代过程的非常常见的结构。
def gen(x_init, n, R=2):
x = x_init
for _ in range(n):
x = R * x * (1-x)
yield x
# execute
df.loc[1:, "Pop"] = list(gen(df.at[0, "Pop"], len(df) - 1))
结果:
print(df)
Pop
0 0.400000
1 0.480000
2 0.499200
3 0.499999
对于小型数据,在这里停下来是完全可以的。但是,如果该函数要执行很多次,您可以考虑使用numba优化生成器。
pip install numba
或conda install numba
首先在控制台中import numba
@numba.njit
在生成器前面添加装饰器。
把s的个数np.nan
改成10^6,自己去看看执行时间的差异。在我的 Core-i5 8250U 64 位笔记本电脑上实现了从 468 毫秒到 217 毫秒的改进。
推荐阅读
- django - 并非我在“render_table”中的所有列都是可订购的,我该怎么办?
- mongodb - mongodb atlas 中的 Lucene $search 管道
- node.js - Discord oauth2 无法获得公会
- vue.js - Vue尾风项目不会运行postcss错误
- flutter - showDialog 之前的颤振加载指示器
- google-cloud-platform - BigQuery 跨区域表同步
- javascript - 当 (document.exists) 不为真“firestore”时,else 语句不起作用
- firebase - 嗨我想问一下谷歌地图颤振:如何查找用户是否在多边形内我尝试过的所有解决方案都不起作用
- javascript - 我正在尝试使用 js 脚本,但它向我显示了这个错误 Uncaught ReferenceError: jQuery is not defined
- nginx - Hugo 上的 XSS JS-AlertBox