我有一个关于用Python动态构建柱状图的概念性问题。我正在尝试找出是否有一个好的算法或者一个现有的包。
我编写了一个函数,它运行蒙特卡洛模拟,被调用100000000次,并在每次运行结束时返回一个64位浮点数。所述功能如下:
def MonteCarlo(df,head,span):
# Pick initial truck
rnd_truck = np.random.randint(0,len(df))
full_length = df['length'][rnd_truck]
full_weight = df['gvw'][rnd_truck]
# Loop using other random trucks until the bridge is full
while True:
rnd_truck = np.random.randint(0,len(df))
full_length += head + df['length'][rnd_truck]
if full_length > span:
break
else:
full_weight += df['gvw'][rnd_truck]
# Return average weight per feet on the bridge
return(full_weight/span)
df
是一个熊猫数据帧对象,其列标记为'length'
和'gvw'
,分别是卡车长度和重量。head
是两辆连续卡车之间的距离,span
是桥梁长度。只要卡车列车的总长度小于桥梁的长度,该功能就将卡车随机放置在桥梁上。最后,计算每英尺桥上现有卡车的平均重量(桥上现有的总重量除以桥的长度)。因此,我想构建一个表格化的柱状图,显示返回值的分布情况,稍后可以绘制出来。我有一些想法:
继续收集numpy向量中的返回值,然后在蒙特卡洛分析完成后使用现有的柱状图函数。这是不可行的,因为如果我的计算是正确的,我将只需要7.5GB的内存用于该向量(100000000064位浮点数~7.5GB)。
用给定的范围和容器数初始化numpy数组。每次运行结束时,将匹配容器中的项目数增加一个。问题是,我不知道我能得到的值的范围。设置一个范围和合适的箱子大小的柱状图是未知的。我还必须弄清楚如何为正确的容器赋值,但我认为这是可行的。
不停地做。每次函数返回数字时,修改范围和肥料箱大小。我想这太难了,从零开始写。
好吧,我打赌有更好的方法来解决这个问题。欢迎有任何想法!
第二个注意事项是,我测试了运行上面的函数100000000次,结果只得到了计算出的最大值(代码段在下面)。当
span = 200
时,这需要大约一个小时。如果我在更长的跨度上运行它,计算时间会增加(而循环运行的时间更长,以便用卡车填满桥梁)。有没有一种方法可以优化你的想法?max_w = 0
i = 1
while i < 1000000000:
if max_w < MonteCarlo(df_basic, 15., 200.):
max_w = MonteCarlo(df_basic, 15., 200.)
i += 1
print max_w
谢谢!
最佳答案
这里有一个可能的解决方案,固定的箱子大小和形式为[K*大小,(K+1)*大小的箱子。函数finalizeBins返回两个列表:一个是bin计数(A),另一个是bin下限(通过添加binsize推导上限)。
import math, random
def updatebins(bins, binsize, x):
i = math.floor(x / binsize)
if i in bins:
bins[i] += 1
else:
bins[i] = 1
def finalizebins(bins, binsize):
imin = min(bins.keys())
imax = max(bins.keys())
a = [0] * (imax - imin + 1)
b = [binsize * k for k in range(imin, imax + 1)]
for i in range(imin, imax + 1):
if i in bins:
a[i - imin] = bins[i]
return a, b
# A test with a mixture of gaussian distributions
def check(n):
bins = {}
binsize = 5.0
for i in range(n):
if random.random() > 0.5:
x = random.gauss(100, 50)
else:
x = random.gauss(-200, 150)
updatebins(bins, binsize, x)
return finalizebins(bins, binsize)
a, b = check(10000)
# This must be 10000
sum(a)
# Plot the data
from matplotlib.pyplot import *
bar(b,a)
show()