更新:显然我只是计算Python读取列表的速度。但这并没有改变我的问题。
所以,前几天我读了this post,想比较速度是什么样的。我是熊猫新手,所以每当我看到有机会做一些适度有趣的事情时,我就会跳上它。无论如何,我最初只用100个数字测试了这个,认为这足以满足我与大熊猫一起玩痒。但这就是图表的样子:
请注意,有3种不同的运行方式。这些运行按顺序运行,但它们在相同的两个点都有峰值。这些点大约是28和64.所以我最初的想法是它与字节有关,特别是4.也许第一个字节包含关于它是列表的附加信息,然后下一个字节是所有数据,每4个字节后导致速度加快,有点有意义。所以我需要用更多数字来测试它。所以我创建了一组包含3组数组的DataFrame,每组数组有1000个列表,长度范围为0-999。然后我以相同的方式计算它们,即:
Run 1: 0, 1, 2, 3, ...
Run 2: 0, 1, 2, 3, ...
Run 3: 0, 1, 2, 3, ...
我期待看到的是数组中大约每32个项目的显着增加,但是模式没有再发生(我确实放大并寻找尖峰):
然而,你会注意到,它们在数字400和682之间变化很大。奇怪的是,1在同一个地方总是出现一个尖峰,使得该模式中的模式更难以区分28和64点。绿线到处都是。可耻。
问题:在最初的两次峰值时发生了什么?为什么它在400和682之间的图形上变得“模糊”?我刚刚完成了0-99集的测试,但这次对数组中的每个项目进行了简单的添加,结果完全是线性的,所以我认为它与字符串有关。
我首先使用其他方法进行了测试,并得到了相同的结果,但图表因为我加入了错误的结果而搞砸了,所以我在一夜之间再次运行它(这需要很长时间)使用此代码来确保时间与索引正确对齐,并按正确的顺序执行运行:
import statistics as s
import timeit
df = pd.DataFrame([[('run_%s' % str(x + 1)), r, np.random.choice(100, r).tolist()]
for r in range(0, 1000) for x in range(3)],
columns=['run', 'length', 'array']).sort_values(['run', 'length'])
df['time'] = df.array.apply(lambda x: s.mean(timeit.repeat(str(x))))
# Graph
ax = df.groupby(['run', 'length']).mean().unstack('run').plot(y='time')
ax.set_ylabel('Time [ns]')
ax.set_xlabel('Array Length')
ax.legend(loc=3)
如果您想查看原始数据,我也会对数据框进行腌制。
答案 0 :(得分:1)
您在此使用pandas
和.apply
严重过度复杂化了。没有必要 - 它效率低下。就像香草Python一样:
In [3]: import timeit
In [4]: setup = "l = list(range({}))"
In [5]: test = "str(l)"
注意,timeit
函数采用number
参数,这是一切运行的次数。它默认为1000000
,所以让我们使用number=100
使其更合理,这样我们就不必永远等待......
In [8]: data = [timeit.repeat(test, setup.format(n), number=100) for n in range(0, 10001, 100)]
In [9]: import statistics
In [10]: mean_data = list(map(statistics.mean, data))
目视检查结果:
In [11]: mean_data
Out[11]:
[3.977467228348056e-05,
0.0012597616684312622,
0.002014552320664128,
0.002637979011827459,
0.0034494600258767605,
0.0046060653403401375,
0.006786816345993429,
0.006134035007562488,
0.006666974319765965,
0.0073876206879504025,
0.008359026357841989,
0.008946725012113651,
0.01020014965130637,
0.0110439983351777,
0.012085124345806738,
0.013095536657298604,
0.013812023680657148,
0.014505649354153624,
0.015109792332320163,
0.01541508767210568,
0.018623976677190512,
0.018014412683745224,
0.01837641668195526,
0.01806374565542986,
0.01866597666715582,
0.021138361655175686,
0.020885809014240902,
0.023644315680333722,
0.022424093661053728,
0.024507874331902713,
0.026360396664434422,
0.02618172235088423,
0.02721496132047226,
0.026609957004742075,
0.027632603014353663,
0.029077719994044553,
0.030218352350251127,
0.03213361800105,
0.0321545610204339,
0.032791375007946044,
0.033749551337677985,
0.03418213398739075,
0.03482868466138219,
0.03569800598779693,
0.035460735321976244,
0.03980560234049335,
0.0375820419867523,
0.03880414469555641,
0.03926491799453894,
0.04079093333954612,
0.0420664346893318,
0.044861480011604726,
0.045125720323994756,
0.04562378901755437,
0.04398221097653732,
0.04668888701902082,
0.04841196699999273,
0.047662509993339576,
0.047592316346708685,
0.05009777001881351,
0.04870589632385721,
0.0532167866670837,
0.05079756366709868,
0.05264475334358091,
0.05531930166762322,
0.05283398299555605,
0.055121281009633094,
0.056162080339466534,
0.05814277834724635,
0.05694748067374652,
0.05985202432687705,
0.05949359833418081,
0.05837553597909088,
0.05975819365509475,
0.06247356999665499,
0.061310798317814864,
0.06292542165222888,
0.06698586166991542,
0.06634997764679913,
0.06443380867131054,
0.06923895300133154,
0.06685209332499653,
0.06864909763680771,
0.06959929631557316,
0.06832000267847131,
0.07180017333788176,
0.07092387134131665,
0.07280202202188472,
0.07342300032420705,
0.0745120863430202,
0.07483605532130848,
0.0734497313387692,
0.0763389469939284,
0.07811927401538317,
0.07915793966579561,
0.08072184936221068,
0.08046915601395692,
0.08565403800457716,
0.08061318534115951,
0.08411134833780427,
0.0865995019945937]
这对我看起来非常线性。现在,pandas
是绘制事物图形的便捷方式,特别是如果您想要一个方便的matplotlib
API包装器:
In [14]: import pandas as pd
In [15]: df = pd.DataFrame({'time': mean_data, 'n':list(range(0, 10001, 100))})
In [16]: df.plot(x='n', y='time')
Out[16]: <matplotlib.axes._subplots.AxesSubplot at 0x1102a4a58>
结果如下:
这可以让你走上正确的轨道,实际计划你想要的时间。正如我在评论中所解释的那样,你结束了时间:
您正在计算
str(x)
的结果,这导致一些列表文字, 所以你正在计算列表文字的解释,而不是 转换list
- &gt;str
我只能推测你所看到的模式,但这很可能取决于解释器/硬件。以下是我在机器上的调查结果:
In [18]: data = [timeit.repeat("{}".format(str(list(range(n)))), number=100) for n in range(0, 10001, 100)]
使用不那么大的范围:
In [23]: data = [timeit.repeat("{}".format(str(list(range(n)))), number=10000) for n in range(0, 101)]
我认为有点看起来像你的。或许这更适合它自己的问题。