2016-08-23 3 views
1

У меня есть вектор 2500 значений, состоящий из повторяющихся значений и значений NaN. Я хочу удалить все значения NaN и вычислить количество вхождений каждого другого значения.Число вхождений элементов в вектор [JULIA]

y 
2500-element Array{Int64,1}: 
8 
43 
NaN 
46 
NaN 
8 
8 
3 
46 
NaN 

Например: количество вхождений 8 составляет 3 количество вхождений 46 2 количество вхождений 43 1.

+0

См. Также http://stackoverflow.com/questions/21172027/count-instances-of-each-unique-integer-in-a-vector-in-1-line-of-code –

ответ

3
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])") 
+0

он работает. но я не могу получить доступ к значению массива по значению, например (6,1), как я могу читать только тогда только 1?. Мне нужно, чтобы нарисовать гистограмму. ось x представляет собой разные значения, а ось y - это количество отсчетов каждого значения. [(i, count (x-> x == i, y)) для i в u] 9-элементный массив {Tuple {Любой, Int64}, 1}: (6,1) (1,2) (7,3) (10,3) (9,3) (2,3) (5,1) (3,2) (8,2) – vincet

+0

только что отредактировано для доступа по значению –

+1

Это работает и очень изящно. Но он много раз проходит массив 'y'. Если у вас много уникальных значений в 'y', он становится невыносимо медленным, легко на несколько порядков медленнее, чем необходимо. 'countmap' избегает этой проблемы. – DNF

6

Для удаления NaN значения, которые можно использовать функция фильтра. Из документов Julia:

фильтра (функция, коллекция)

вернуть копию коллекции, удаление элементов, для которых функция является ложной.

x = filter(y->!isnan(y),y) 
filter!(y->!isnan(y),y) 

Таким образом, мы создаем в нашей функции условной !isnan(y) и использовать ее для фильтрации массива y (примечание, мы могли бы также написали с помощью z или любой другой переменной мы выбрали, так как первый аргумент filter просто определяет встроенную функцию). Обратите внимание: мы можем либо сохранить это как новый объект, либо использовать версию модификации на месте, сигнализированную !, чтобы просто изменить существующий объект. y

Затем, до или после этого, в зависимости от того, хотим ли мы чтобы включить NaN s в наш счет, мы можем использовать функцию countmap() из StatsBase. Из документов Julia:

countmap (х)

Вернуться словарь отображения каждое уникальное значение х его количества вхождений.

using StatsBase 
a = countmap(y) 

вы можете получить доступ к определенным элементам этого словаря, например, a[-1] покажет вам, сколько вхождений есть из -1

Или, если вы хотите, чтобы затем преобразовать этот словарь в массив, вы можете использовать:

b = hcat([[key, val] for (key, val) in a]...)' 

Примечание: Благодаря @JeffBezanon для комментариев на правильном метод фильтрации NaN значений.

+0

Фильтрация с помощью 'y-> y ! = NaN' не работает, потому что 'NaN! = NaN' истинно (согласно правилам арифметики с плавающей точкой IEEE). Вместо этого вы можете фильтровать с помощью 'y ->! Isnan (y)'. –

+1

@JeffBezanson Хороший улов, спасибо! Я исправил его в ответе. –

2

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 

Решения в принятом ответе может быть немного быстрее, если есть очень небольшое количество уникальных значений, но в противном случае плохо масштабируется.

Edit: Потому что я просто не мог оставить в покое, вот версия, которая является более общим, а также быстрее (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 
Смежные вопросы