2016-08-23 1 views
1

Ich habe einen Vektor von 2500 Werten, die sich aus wiederholten Werten und NaN Werten zusammensetzen. Ich möchte alle NaN Werte entfernen und die Anzahl der Vorkommen jedes anderen Werts berechnen.Die Anzahl der Vorkommen von Elementen in einem Vektor [JULIA]

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

Zum Beispiel: die Anzahl der Vorkommen von 8 3 die Anzahl der Vorkommen von 46 2 die Anzahl von Vorkommnissen von 43 ist 1.

+0

Siehe auch http://stackoverflow.com/questions/21172027/count-instances-of-each-unique-integer-in-a-vector-in-1-line-of-code –

Antwort

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

funktioniert es. aber ich kann nicht auf den Array-Wert nach Wert zugreifen, zum Beispiel (6,1) wie kann ich nur dann nur 1? lesen. Ich brauche das, um ein Histogramm zu zeichnen. x-Achse stellt die verschiedenen Werte und die y-Achse ist die Anzahl der occurnces jeden Wertes. [(i, count (x-> x == i, y)) für i in u] 9-Element-Array {Tuple {Any, Int64}, 1}: (6,1) (1,2) (7,3) (10,3) (9,3) (2,3) (5,1) (3,2) (8,2) – vincet

+0

nur für den Zugriff von Wert bearbeitet –

+1

Das funktioniert und ist sehr elegant. Aber es passiert das Array "y" viele Male. Wenn Sie viele eindeutige Werte in "y" haben, wird es unerträglich langsam, leicht mehrere Größenordnungen langsamer als nötig. 'countmap' vermeidet dieses Problem. – DNF

6

NaN die Werte löschen Sie verwenden können, die Filterfunktion. Aus der Julia docs:

Filter (Funktion, Sammlung)

Rückkehr einer Kopie der Sammlung, Entfernen von Elementen, für die Funktion falsch ist.

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

So haben wir als unsere Aufgabe erstellen die bedingte !isnan(y) und es verwenden, um das Array y (Anmerkung filtern wir auch geschrieben haben könnte z oder jede andere Variable verwenden wir gewählt haben, da das erste Argument von filter definiert nur eine Inline-Funktion). Beachten Sie, dass wir dies entweder als neues Objekt speichern oder die Version "In Place" verwenden können, die durch ! signalisiert wird, um das vorhandene Objekt einfach zu ändern. Je nachdem, ob wir es möchten oder nicht Um die NaN s in unserer Zählung einzuschließen, können wir die countmap() Funktion von StatsBase verwenden. Aus der Julia docs:

countmap (x)

Return ein Wörterbuch Mapping jeden eindeutiger Wert in x zu seiner Anzahl von Vorkommen.

using StatsBase 
a = countmap(y) 

Sie können dann bestimmte Elemente dieses Wörterbuch zugreifen, z.B. a[-1] wird Ihnen sagen, wie viele Vorkommen gibt es von -1

Oder wenn Sie das Wörterbuch in ein Array konvertieren Sie wollten, könnten Sie verwenden:

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

Hinweis: Vielen Dank für die Kommentare zu richtig @JeffBezanon Methode zum Filtern NaN Werte.

+0

Filtering mit 'y-> y ! = NaN' funktioniert nicht, weil 'NaN! = NaN' wahr ist (gemäß den Regeln der IEEE-Gleitkomma-Arithmetik). Stattdessen können Sie mit 'y ->! Isnan (y) 'filtern. –

+1

@JeffBezanson Guter Fang, danke! Ich habe es in der Antwort korrigiert. –

2

countmap ist die beste Lösung, die ich bisher gesehen habe, aber hier ist eine schriftliche out-Version, die nur etwas langsamer ist. Es geht nur über das Array einmal, wenn Sie also viele eindeutige Werte haben, ist es sehr effizient:

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 

Die Lösung in der akzeptierte Antwort ein bisschen schneller sein kann, wenn es eine sehr kleine Anzahl von eindeutigen Werten sind, aber ansonsten schlecht skaliert.

bearbeiten: Weil ich kann einfach nicht gut genug allein lassen, hier ist eine Version, die allgemeinere und auch schneller (countmap akzeptiert keine Strings, Sätze oder Tupeln, zum Beispiel) ist:

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 
Verwandte Themen