我有一个由重复值和NaN值组成的2500个值的向量.我想删除所有NaN值并计算每个其他值的出现次数.
y
2500-element Array{Int64,1}:
8
43
NaN
46
NaN
8
8
3
46
NaN
Run Code Online (Sandbox Code Playgroud)
例如:8的出现次数为3次,46次出现次数为2次,出现次数为43次为1次.
要删除NaN值,可以使用过滤器功能.来自朱莉娅的文档:
过滤器(功能,集合)
返回集合的副本,删除函数为false的元素.
x = filter(y->!isnan(y),y)
filter!(y->!isnan(y),y)
Run Code Online (Sandbox Code Playgroud)
因此,我们创建条件!isnan(y)并使用它来过滤数组y(注意,我们也可以filter(z->!isnan(z),y)使用z我们选择的任何其他变量,因为第一个参数filter只是定义内联函数).注意,我们可以将其保存为新对象,也可以使用"就地修改"版本,!以便通过简单的方式修改现有对象y
然后,在此之前或之后,根据我们是否要NaN在计数中包含s,我们可以使用countmap()StatsBase中的函数.来自朱莉娅的文档:
countmap(x)的
返回一个字典,将x中的每个唯一值映射到其出现次数.
using StatsBase
a = countmap(y)
Run Code Online (Sandbox Code Playgroud)
然后,您可以访问此词典的特定元素,例如,a[-1]它将告诉您有多少次出现-1
或者,如果您想将该字典转换为数组,则可以使用:
b = hcat([[key, val] for (key, val) in a]...)'
Run Code Online (Sandbox Code Playgroud)
注意:感谢@JeffBezanon对过滤NaN值的正确方法的评论.
countmap是迄今为止我见过的最好的解决方案,但这里有一个书面版本,只是稍微慢一些。它只传递数组一次,所以如果你有很多唯一值,它是非常有效的:
function countmemb1(y)
d = Dict{Int, Int}()
for val in y
if isnan(val)
continue
end
if val in keys(d)
d[val] += 1
else
d[val] = 1
end
end
return d
end
Run Code Online (Sandbox Code Playgroud)
如果唯一值的数量非常少,则接受的答案中的解决方案可能会更快一些,但否则扩展性很差。
编辑:因为我无法单独处理,所以这里有一个更通用且速度更快的版本(countmap例如,不接受字符串、集合或元组):
function countmemb(itr)
d = Dict{eltype(itr), Int}()
for val in itr
if isa(val, Number) && isnan(val)
continue
end
d[val] = get(d, val, 0) + 1
end
return d
end
Run Code Online (Sandbox Code Playgroud)
y=rand(1:10,20)
u=unique(y)
d=Dict([(i,count(x->x==i,y)) for i in u])
println("count for 10 is $(d[10])")
Run Code Online (Sandbox Code Playgroud)