2014-04-27 3 views
5

Unten ist eine Teilmenge von meinen Daten:R: Offset-Differenzen zwischen den Elementen in Datenrahmen Berechnung mit dem gleichen Identifikator

> head(dt) 

    name start  end 
1: 1 3195984 3197398 
2: 1 3203519 3205713 
3: 2 3204562 3207049 
4: 2 3411782 3411982 
5: 2 3660632 3661579 
6: 3 3638391 3640590 

dt <- data.frame(name = c(1, 1, 2, 2, 2, 3), start = c(3195984, 
3203519, 3204562, 3411782, 3660632, 3638391), end = c(3197398, 
3205713, 3207049, 3411982, 3661579, 3640590)) 

Ich mag eine anderen Wert berechnen: die Differenz zwischen dem Ende der Zeile n-Koordinate und der Startkoordinate von Zeile n + 1, aber nur wenn beide Elemente einen Namen teilen. Auszuarbeiten das ist, was ich will ein resultierendes Datenrahmen wie folgt aussehen:

name start  end dist 
1: 1 3195984 3197398 
2: 1 3203519 3205713 -6121 
3: 2 3204562 3207049 
4: 2 3411782 3411982 −204733 
5: 2 3660632 3661579 −248650 
6: 3 3638391 3640590 

Der Grund, warum ich dies tun wollen, ist, dass ich für dist Werte bin auf der Suche, die positiv sind. Eine Möglichkeit, die ich versucht habe, ist, die Anfangs- und Endkoordinaten auszugleichen, aber dann stoße ich auf ein Problem, bei dem ich Dinge mit verschiedenen Namen vergleiche.

Wie macht man das in R?

+0

Ist das ein 'data.table' eher als ein' data.frame'? Es sieht aus wie die Zeilennamen drucken. Wenn dies der Fall ist, eröffnet das einige andere Möglichkeiten für Antworten. – thelatemail

+0

@thelatemail '> Klasse (dt)' gibt: '[1]" data.frame "'. Wäre es am besten zu versuchen, in eine 'data.table' zu ​​konvertieren? – reedms

+0

Nein, nicht unbedingt, sie unterscheiden sich nur geringfügig in Bezug auf mögliche Lösungen. – thelatemail

Antwort

5

A data.table Lösung hier gut sein kann:

library(data.table) 
dt <- as.data.table(dt) 
dt[, dist := c(NA, end[-(length(end))] - start[-1]) , by=name] 
dt 

# name start  end dist 
#1: 1 3195984 3197398  NA 
#2: 1 3203519 3205713 -6121 
#3: 2 3204562 3207049  NA 
#4: 2 3411782 3411982 -204733 
#5: 2 3660632 3661579 -248650 
#6: 3 3638391 3640590  NA 

Vorausgesetzt, dass Ihre Daten sortiert sind, können Sie auch tun Sie es mit Basis R-Funktionen:

dt$dist <- unlist(
    by(dt, dt$name, function(x) c(NA, x$end[-(length(x$end))] - x$start[-1])) 
) 
+0

Ich bekomme ein 'nicht-numerisches Argument zum binären Operator' mit diesem Code. Also mein Anfang und Ende werden als Faktoren betrachtet, denke ich. Wäre der richtige Weg, dies zu beheben, die Verwendung von 'length (as.numeric (as.character (end)))' im Code? – reedms

+0

Wenn Sie numerische Daten haben, die als Faktor gespeichert werden, würde ich es numerisch machen, um mit den Berechnungen zu beginnen: 'dat $ start <- as.numeric (as.character (dat $ start)) 'usw. Achten Sie jedoch darauf, welche Daten Sie mit dieser Konvertierung wegwerfen. – thelatemail

1

Mit dplyr (mit Kredit für die Berechnung des dist @thelatemail):

library(dplyr) 

dat.new <- dt %.% 
    group_by(name) %.% 
    mutate(dist = c(NA, end[-(length(end))] - start[-1])) 
+0

@thelatemail - gute Abholung. – alexwhan

0

Hier ist eine andere dplyr Lösung:

dt %.% group_by(name) %.% mutate(dist = lag(end) - start) 

geben:

Source: local data frame [6 x 4] 
Groups: name 

    name start  end dist 
1 1 3195984 3197398  NA 
2 1 3203519 3205713 -6121 
3 2 3204562 3207049  NA 
4 2 3411782 3411982 -204733 
5 2 3660632 3661579 -248650 
6 3 3638391 3640590  NA 
Verwandte Themen