作者uranusjr (←这人是超级笨蛋)
看板Python
标题Re: [问题] 删除大量数据的速度问题
时间Thu Nov 5 16:17:02 2015
※ 引述《stba5328 (St. Ba)》之铭言:
: 想请问一下
: 我想从x, y两个元素数量相等list当中,删除所有值为-9999的项,
: 并且另一list同index的项目也要删除,但因为list中大概有180万笔,
: -9999的联集数量大概57万笔,该如何加速以下的程序呢?
: def get_index(a):
: lst = [i for i, j in enumerate(a) if j == -9999]
: return lst
: indx = get_index(x)
: indy = get_index(y)
: indlst = list(set(indx) | set(indy))
: xlst = [j for i, j in enumerate(x) if i not in indx]
: ylst = [j for i, j in enumerate(y) if i not in indy]
最高指导原则:各 list 中各个元素只看一次
因为你有那麽多资料, 当然是看越少次越好
所以只能用一个 for 回圈, 就要把两个串列走完
可以这样想:
-------------------
| x[0] | y[0] |
-------------------
| x[1] | y[1] |
-------------------
| x[2] | y[2] |
-------------------
| x[3] | y[3] |
. .
. .
. .
然後从上面往下走一次
如果 x[i] 与 y[i] 其中有一个是 -9999, 就舍去那一栏
把它写成程式
BAD_VALUE = -9999
result_x = []
result_y = []
for xi, yi in zip(x, y): # Python 2 改用 izip
if x_i == BAD_VALUE or y_i == BAD_VALUE:
continue # 不要这行
result_x.append(xi)
result_y.append(yi)
这是浅显易懂的简化
若想再加速(用纯 Python 为前题), 最简单的方法是改用 PyPy
如果无法这样做, 那麽就要想办法拿掉 Python 的 for 回圈
用 list comprehension 是一个方式:
result_rows = [
(xi, yi) for xi, yi in zip(x, y)
if x_i != BAD_VALUE and y_i != BAD_VALUE
]
但这样出来的就不是两个 lists, 而是像上面那样的二维表格
当然你可以再用一个 zip 转置它:
result_x, result_y = zip(result_rows)
但这样就会 iterate 第二次了, 效能上就会有差
(注意这不见得会比前面用回圈的方法慢!)
所以还是要看需求来选用
如果要再加速, 就得借用其他工具了
例如 numpy array 是一个方法
用 Cython 把这个 for 回圈 transcompile 成 C 应该也是解
但这里就不讨论到那边
--
「我最想要的同伴嘛,首先是要笑口常开,其次是我们能永远不会发生误会。
如果这些都能办到的话,嗯,如果他是世界上第一流的桥手,也还不错。」
-- 班尼多‧加罗素,前义大利蓝队成员
--
※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 1.162.122.14
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/Python/M.1446711425.A.0D4.html
※ 编辑: uranusjr (1.162.122.14), 11/05/2015 16:17:35
1F:推 stba5328: 感谢u大!但到最後分离x, y的步骤会显示to many values 11/06 20:51
2F:→ stba5328: to unpack 但 用numpy array 转置後就完成了 感谢! 11/06 20:51