我有Vector
Vector
个不同长度的W
cdfdict = Dict{Tuple{Int,Int},Float64}()
for i in 1:length(W)
v = W[i]
len = length(v)
if len == 0
pcdf = 1.0
else
for j in 0:5:150_000
pcdf = length(v[v .<= j])/len
cdfdict[i, j] = pcdf
end
end
end
。这些最后的向量包含0到150,000之间的整数,步长为5,但也可以为空。我试图计算每个向量的经验cdf。我可以计算这些cdf遍历每个向量和每个整数,如此
j >= maximum(v)
但是,这种方法效率低,因为maximum(v)
的cdf等于1,有时j
远低于150,000。
我的问题是:我如何包含一个条件,该条件会突破j > maximum(v)
的{{1}}循环,但仍会为其余的pcdf = 1.0
分配j
?< / p>
我尝试在break
时添加j > maximum(v)
,但这当然会阻止循环继续j
的剩余时间。此外,我可以打破循环,然后使用get!
来访问/包含1.0
以后在cdfdict
中找不到的密钥,但这不是我正在寻找的。
答案 0 :(得分:2)
break
只有一个等级。您可以通过包装for循环函数并使用return
(而不是放置它的地方)或使用@goto
来执行您想要的操作。
或者您要破解的地方,您可以切换布尔值breakd=true
然后中断,并在较大的循环底部执行if breakd break end
。
答案 1 :(得分:2)
您可以使用另一个for
循环将所有剩余元素设置为1.0。内环变为
m = maximum(v)
for j in 0:5:150_000
if j > m
for k in j:5:150_000
cdfdict[i, k] = 1.0
end
break
end
pcdf = count(x -> x <= j, v)/len
cdfdict[i, j] = pcdf
end
然而,这很难理解。使用分支会更容易。事实上,这应该同样快,因为分支是非常可预测的。
m = maximum(v)
for j in 0:5:150_000
if j > m
cdfdict[i, j] = 1.0
else
pcdf = count(x -> x <= j, v)/len
cdfdict[i, j] = pcdf
end
end
答案 2 :(得分:2)
详细说明我的评论,这个答案详述了一个填充数组而不是Dict的实现。
首先创建一个随机测试用例:
W = [rand(0:mv,rand(0:10)) for mv in floor(Int,exp(log(150_000)*rand(10)))]
接下来创建一个填充1.0s的正确大小的数组:
cdfmat = ones(Float64,length(W),length(0:5:150_000));
现在填写CDF的开头:
for i=1:length(W)
v = sort(W[i])
k = 1
thresh = 0
for j=1:length(v)
if (j>1 && v[j]==v[j-1])
continue
end
pcdf = (j-1)/length(v)
while thresh<v[j]
cdfmat[i,k]=pcdf
k += 1
thresh += 5
end
end
end
此实现使用sort
,有时可能会很慢,但其他实现基本上将向量与各种值进行比较,在大多数情况下这些值甚至更慢。
答案 3 :(得分:1)
另一个答案给出了使用Array的实现,该Array通过对样本进行排序并用分位数值填充CDF箱来计算CDF。因为整个数组因此被填充,所以在阵列上进行另一次传递不应该过于昂贵(我们已经容忍了单次传递)。通过计算阵列中的直方图并使用cumsum
生成CDF,可以避免排序位及其伴随的分配。也许代码会更好地解释这个:
初始化尺寸,长度和宽度:
n = 10; w = 5; rmax = 150_000; hl = length(0:w:rmax)
制作示例示例:
W = [rand(0:mv,rand(0:10)) for mv in floor(Int,exp(log(rmax)*rand(n)))];
计算CDF:
cdfmat = zeros(Float64,n,hl); # empty histograms
for i=1:n # drop samples into histogram bins
for j=1:length(W[i])
cdfmat[i,1+(W[i][j]+w-1)÷5]+=one(Float64)
end
end
cumsum!(cdfmat,cdfmat,2) # calculate pre-CDF by cumsum
for i=1:n # normalize each CDF by total
if cdfmat[i,hl]==zero(Float64) # check if histogram empty?
for j=1:hl # CDF of 1.0 as default (might be changed)
cdfmat[i,j] = one(Float64)
end
else # the normalization factor calc-ed once
f = one(Float64)/cdfmat[i,hl]
for j=1:hl
cdfmat[i,j] *= f
end
end
end
(a)注意使用one
,zero
来准备改变Real类型 - 这是一种很好的做法。 (b)同时添加各种@inbounds
和@simd
应进一步优化。 (c)建议将此代码放在一个函数中(本答案中没有这样做)。 (d)如果空样本的CDF为零(这意味着没有样本在语义上意味着巨大的样本),那么第二个for
可以简化。
有关更多选项,请参阅其他答案,并提醒:过早优化是所有邪恶的根源(Knuth ??)