我有一个包含圆的所有半径的列表,我正在尝试用对角线半径计算圆的直径。
我的示例功能如下:
radii=[2.1, 2.4, 2.3, 2.2, 2.0, 2.2, 2.5, 2.1]
def dia(radius):
Diameter = []
for i in range(int(len(radii)/2)):
print i
Diameter.append(radii[i]+radii[int(len(radii)/2+i)])
print Diameter
dia(radii)
现在这适用于相对较小的数据集。但每当我有一个圆圈,让我说100半径,我有约10万圈。这个功能变得非常慢,并且运行所有这些功能需要很长时间。我想知道如何使用numpy或任何python工具加快速度。有人有想法吗?
答案 0 :(得分:2)
在NumPy中你可以简单地这样做:
>>> radii = np.array([2.1, 2.4, 2.3, 2.2, 2.0, 2.2, 2.5, 2.1])
>>> radii[:len(radii)/2] + radii[len(radii)/2:]
array([ 4.1, 4.6, 4.8, 4.3])
这比基于列表推导的Python版本的代码要快得多。
>>> radii = [2.1, 2.4, 2.3, 2.2, 2.0, 2.2, 2.5, 2.1]*10**6
>>> radii_a = np.array(radii)
>>> %timeit [radii[i]+radii[int(len(radii)/2+i)] for i in xrange(int(len(radii)/2))]
1 loops, best of 3: 806 ms per loop
>>> %timeit radii_a[:len(radii)/2] + radii_a[len(radii)/2:]
100 loops, best of 3: 11.2 ms per loop
请注意,Python代码太慢,因为每次len()
,int()
都发生了很多全局查找(是的,我们可以删除Python 2中的int()
调用)等等:
>>> %timeit le = int(len(radii)/2); [radii[i]+radii[le+i] for i in xrange(le)]
1 loops, best of 3: 300 ms per loop
答案 1 :(得分:2)
这很简单:numpy:
radii=np.array([2.1, 2.4, 2.3, 2.2, 2.0, 2.2, 2.5, 2.1])
diameters = radii[:radii.size/2] + radii[radii.size/2:]
答案 2 :(得分:1)
首先,正如Ashwini Chaudhary和ebarr所解释的那样,你可以将内部循环从100个半径转换为从Python循环到NumPy循环:
radii = np.array([2.1, 2.4, 2.3, 2.2, 2.0, 2.2, 2.5, 2.1])
radii[:len(radii)/2] + radii[len(radii)/2:]
但您可能还想考虑通过使用2D数组而不是数组列表将外部循环更改为NumPy循环:
circles = np.array([[2.1, 2.4, 2.3, 2.2, 2.0, 2.2, 2.5, 2.1],
[2.1, 2.4, 2.3, 2.2, 2.0, 2.2, 2.5, 2.1]])
circles[:,:circles.shape[1]/2] + circles[:,circles.shape[1]/2:]
比较100个半径的100k随机圆的时间,我只需要更换内循环就可以获得11.3倍的加速,从更换两个循环后加速36.8倍。所以,它不是一个好处的很多,但它仍然绝对值得做...假设你可以立刻把你所有的圈子都放在记忆中。
最后一句似乎对这种可能性不屑一顾(你的评论意味着你采取了这种方式),但要弄清楚我们在这里谈论多少记忆。你有~100k个圆圈,每个圆圈有100个半径,所以半径约为10米。每个都是float64
,占用8个字节。另外还有100个字节左右的数组头。意思是我们在80MB以下说话。那个没什么。除非您期望在未来处理至少一个数量级的数据,否则将所有内容放入2D阵列的速度和便利性几乎肯定是一种胜利。