当前位置: 首页 > news >正文

【Python性能优化实例】计算 numpy 数组首尾为 0 的数量

import numpy as np
import timeit
测试数据

开头有 30000 个 0 元素,中间有 100000 个非 0 元素,结尾有 70000 个为 0 元素的 numpy 数组。下面以计算数组末尾的零的数量为例。

array = np.array([0] * 30000 + [i for i in range(1, 1000001)] + [0] * 70000)
方法 1

使用 Python 的循环,从后向前遍历 numpy 数组并统计为 0 元素的个数,当遇到非 0 元素时,则跳出循环。

res1 = 0
for i in range(array.shape[0] - 1, -1, -1):
    if array[i] == 0:
        res1 += 1
    else:
        break
方法 2

先使用 numpy 的切片器倒序数组,然后使用 numpy 的 consum 的函数计算前缀和;此时除原数组末尾的 0 元素外的其他元素均已变为非 0 元素。于是,先使用 numpy 的 count_nonzero 方法统计满足元素值等于 0 的元素数量。

numpy 的 参考文档:https://numpy.org/doc/stable/reference/generated/numpy.cumsum.html

res2 = np.count_nonzero(np.cumsum(array[::-1]) == 0)
方法 3

在方法 2 的基础上,先直接统计非 0 元素数量,再使用元素总数减去非 0 元素数量得到 0 元素数量。

res3 = array.shape[0] - np.count_nonzero(np.cumsum(array[::-1]))
结果检查
assert res1 == res2 == res3
性能检查

方法 1 计算时间:1.6362712000000001

print(timeit.timeit(
    "res = 0\n"
    "for i in range(array.shape[0] - 1, -1, -1):\n"
    "    if array[i] == 0:\n"
    "        res += 1\n"
    "    else:\n"
    "        break",
    setup="import numpy as np\n"
          "array = np.array([0] * 30000 + [i for i in range(1, 1000001)] + [0] * 70000)",
    number=100
))

方法 2 计算时间:0.4067506000000001

因为使用了 numpy 函数替代了 Python 的原生循环,因此性能提升较多。

print(timeit.timeit(
    "np.count_nonzero(np.cumsum(array[::-1]) == 0)",
    setup="import numpy as np\n"
          "array = np.array([0] * 30000 + [i for i in range(1, 1000001)] + [0] * 70000)",
    number=100
))

方法 3 计算时间:0.33288949999999984

因为节省了一次计算数组中元素是否等于 0 的判断操作,因此性能有所提升。

print(timeit.timeit(
    "array.shape[0] - np.count_nonzero(np.cumsum(array[::-1]))",
    setup="import numpy as np\n"
          "array = np.array([0] * 30000 + [i for i in range(1, 1000001)] + [0] * 70000)",
    number=100
))

相关文章:

  • C语言百日刷题第九天
  • 「避坑宝典」为大家分享笔者在22 年所遇到“匪夷所思”的 Bug 趣事
  • 什么是JUC
  • 图解LeetCode——775. 全局倒置与局部倒置(难度:中等)
  • apache 组件下载地址
  • 【JavaSE】继承那些事儿
  • 【数据结构】栈基本操作的实现(C语言)
  • MySQL纯代码复习
  • akshare复权算法-港股复权后数据代码分享
  • 通俗易懂话GC-C#的内存管理
  • 使用小程序制作一个电子木鱼,功德+1
  • Android Studio App开发之实现底部标签栏BottomNavigationView和自定义标签按钮实战(附源码 超详细必看)
  • Vue/Vuex (actions) 核心概念 使用方法、辅助函数 mapActions使用方法说明
  • Flink学习:Flink支持的数据类型
  • 【论文复现】——FEC: Fast Euclidean Clustering for Point Cloud Segmentation
  • 第十三届蓝桥杯C++B组省赛 I 题——李白打酒加强版 (AC)
  • 队列的简单实现
  • java毕业设计家庭理财记账系统(附源码、数据库)
  • 【ASM】字节码操作 工具类与常用类 asm-utils 与 asm-commons
  • 用Python把附近的足浴店都给采集了一遍,好兄弟:针不戳~
  • 即日起,“应急使命·2025”演习公开征集新质救援能力
  • 马上评丨上热搜的协和“4+4”模式,如何面对舆论审视
  • 智能终端出海服务创新联合体成立
  • 打工人的“小长假模式”,已经迫不及待地开启了
  • 夜读丨怀念那个写信的年代
  • 日韩 “打头阵”与美国贸易谈判,汽车、半导体产业忧虑重重