2016-03-21 7 views
5

Lassen Sie uns sagen, ich habe diese ganze Zahl vector:Summe der Intervalle Längen von einem ganzzahligen Vektor

> int.vec 
[1] 1 2 3 5 6 7 10 11 12 13 

(von int.vec <- c(1:3,5:7,10:13) erstellt)

Ich suche nach einer Funktion, die die Summe der Längen zurück aller Intervalle in diesem Vektor.

Also im Grunde für int.vec diese Funktion zurück:

3+3+4 = 10 
+0

Sie die ' – akrun

+11

wird dies immer nicht' Länge (int.vec) 'diff' Funktion können Sie verwenden kann? – SymbolixAU

+0

@Symbolix, das ist die beste Antwort für dieses :-) – A5C1D2H2I1M1N2O1R2T1

Antwort

4

Wir eine Gruppenvariable, indem die Differenz benachbarter Elemente erstellen können, prüfen Sie, ob das nicht gleich 1 ist, erhalten die cumsum, verwenden tapply zu Holen Sie sich die length und sum den Ausgang.

sum(tapply(int.vec,cumsum(c(TRUE,diff(int.vec) !=1)), FUN=length)) 
#[1] 10 

Oder nutzen table und sum

sum(table(int.vec,cumsum(c(TRUE,diff(int.vec) !=1)))) 
#[1] 10 

Oder wir split die "int.vec" mit der Gruppenvariable aus cumsum abgeleitet (split ist sehr schnell) und bekommen die length von jedem list Element mit lengths (eine andere schnelle Option) - beigetragen von @ Frank

sum(lengths(split(int.vec, cumsum(c(0,diff(int.vec)>1))))) 

HINWEIS: Keine Pakete verwendet. Dies ist hilfreich für die Identifizierung der einzelnen length jeder Komponente (falls wir das benötigten), indem Sie nur die sum Wrapper entfernen.


Basierend auf weitere Erkenntnisse aus @ Symbolix-Lösung, die erwartete Ausgabe des OP ist nur der length des vector.

NROW(int.vec) 
#[1] 10 

kann auch verwendet werden. Dies funktioniert auch, wenn wir mit data.frame arbeiten. Aber, wie ich oben erwähnt habe, scheint es, dass das OP sowohl die length jedes Intervalls als auch die length identifizieren muss. Diese Lösung bietet beides.

+1

Könnte auch die neue "Längen" -Funktion 'sum nutzen (Längen (geteilt (int.vec, cumsum (c (0, diff (int.vec)> 1))))) '. Ich nehme an, der Downvote war, weil Sie nicht identifiziert haben, dass die OP-Ausgabe die gleiche ist wie 'Länge (int.vec)' – Frank

+0

@Frank Danke, dafür. Aber ich frage mich, ob "Längen" in der Kreuzplattform funktionieren würden. Letzte Woche habe ich eine (von mir gebaute) Vorhersage-App mit Alteryx getestet. Obwohl ich die aktuelle Version von R verwendete, funktionierte "Längen" nicht. – akrun

+1

Hm, gut zu wissen. Zuerst habe ich davon gehört. – Frank

12

Das Paket "cgwtools" hat eine Funktion namens seqle, die hier hilfreich sein kann.

library(cgwtools) 
int.vec <- c(1:3,5:7,10:13) 
seqle(int.vec) 
# Run Length Encoding 
# lengths: int [1:3] 3 3 4 
# values : int [1:3] 1 5 10 

Das Ergebnis ist ein list, so dass Sie nur mit den "Längen" Werte zugreifen können und die Summe:

sum(seqle(int.vec)$lengths) 
# [1] 10 
12
length(int.vec) 
# 10 

Ihre Intervalle Zahlenfolgen sind, x1:xn, x1:xm, x1:xp, wobei die Länge jedes Vektors (oder Intervalls in diesem Fall) n, m bzw. p ist.

Die Länge des gesamten Vektors ist length(x1:xn) + length(x1:xm) + length(x1:xp), die die gleiche wie length(n + m + p) ist.


Wenn wir nun in der Länge jedes einzelnen Vektor von Sequenzen wirklich interessiert sind, können wir

tun
int.vec <- c(1:3,5:7,10:13) 

## use run-length-encoding (rle) to find sequences where the difference == 1 
v <- rle(diff(int.vec) == 1)[[1]] 
v[v!=1] + 1 
# [1] 3 3 4 

Und wie durch @AHandcartAndMohair wies darauf hin, wenn Sie mit einem arbeiten Liste Sie lengths

int.list <- list(c(1:3), c(5:7), c(10:13)) 
lengths(int.list) 
# [1] 3 3 4 
+2

Kombiniert damit, wenn sie 'list' anstelle von' c' verwenden, könnten sie die 'length' Funktion verwenden, um den 3, 3, 4 Vektor zu bekommen (also offensichtlich, sum (lengths (int.vec)) 'um die Gesamtlänge zu erhalten – A5C1D2H2I1M1N2O1R2T1

+0

@AHandcartAndMohair Danke - Ich habe das zu meiner Antwort hinzugefügt :) – SymbolixAU

Verwandte Themen