2016-07-18 12 views
3

Ich habe 2 Datenrahmen:für Bereiche in Datenrahmen der Suche Werte

> access 
    V1  V2  V3 
1 chr10 136122 136533 
2 chr10 179432 179769 
3 chr10 182988 183371 
4 chr10 224234 224489 
5 chr10 237693 237958 

und

> peaks 
    V1  V2  V3 
1 chr10 126122 126533 
2 chr10 179450 179730 
3 chr10 182788 183350 
4 chr10 224244 224500 
5 chr10 237695 237950 

Die coloumn V2 und V3 sind Start und Ende der Regionen (Bereich) in beiden Datenrahmen . Ich möchte diese Zeilen in peaks Datenrahmen, für die access$V1 == peaks$V1 UND die in den Bereich (oder Regionen) von access Datenrahmen fallen. Zum Beispiel wird das neue Datenrahmen wie: peaks Datenrahmen des

  • 1. Reihe Region nicht in access Datenrahmen existiert, so wird es Kategorie U zugeordnet werden.

  • 2. Reihe von peaks fällt in dem gegebenen Bereich in access Datenrahmen (2. Reihe) und die Kategorie B zugewiesen.

  • 3. Reihe von peaks nicht vollständig in dieser Region fallen, aber es überlappt irgendwie mit Region in 3. Reihe von access, dafür werde ich Kategorie A zuweisen.

  • 4. Reihe von peaks auch nicht vollständig überlappen, um es 11 Zahl nach dem Ende der Region endet in Zeile 4 des Zugangs, wird dies auch A in Kategorie sein.

  • 5. Reihe fällt in der Region wird daher in Kategorie B.

Erwartete Ausgabe:

> newdf 
    V1  V2  V3 V4 
1 chr10 126122 126533 U 
2 chr10 179450 179730 B 
3 chr10 182788 183350 A 
4 chr10 224244 224500 A 
5 chr10 237695 237950 B 

Hier sind die dput von Eingangsdatenrahmen:

> dput(peaks) 
structure(list(V1 = structure(c(1L, 1L, 1L, 1L, 1L), .Label = "chr10", class = "factor"), 
    V2 = c(126122L, 179450L, 182788L, 224244L, 237695L), V3 = c(126533L, 
    179730L, 183350L, 224500L, 237950L)), .Names = c("V1", "V2", 
"V3"), class = "data.frame", row.names = c(NA, -5L)) 

> dput(access) 
    structure(list(V1 = structure(c(1L, 1L, 1L, 1L, 1L), .Label = "chr10", class = "factor"), 
     V2 = c(136122L, 179432L, 182988L, 224234L, 237693L), V3 = c(136533L, 
     179769L, 183371L, 224489L, 237958L)), .Names = c("V1", "V2", 
    "V3"), class = "data.frame", row.names = c(NA, -5L)) 

Edit:

Mein neuer Zugang df sieht wie folgt aus und jetzt möchte ich auch app Ende der letzten Spalte in meinem letzten Ausgabe df:

> access 
    V1  V2  V3 V4 
1 chr10 136122 136533 found 
2 chr10 179432 179769 notFound 
3 chr10 182988 183371 found 
4 chr10 224234 224489 found 
5 chr10 237693 237958 notFound 

So, jetzt gibt eine zusätzliche Bedingung ist, das ist, wenn Zeile in Zugang in Spitzen fällt Bereich dann auch den Wert in V4 in einer neuen Spalte in final df anhängen, wenn Eine Region wird nicht gefunden. Standardmäßig wird notFound angezeigt. Daher wird die endgültige Ausgabe sein:

> newdf 
    V1  V2  V3 V4 V5 
1 chr10 126122 126533 U notFound 
2 chr10 179450 179730 B notFound 
3 chr10 182788 183350 A found 
4 chr10 224244 224500 A found 
5 chr10 237695 237950 B notFound 

Hier in row1$V5 der Wert NOTFOUND ist da dieser Bereich nicht gefunden wurde und in den übrigen Fällen haben wir die Werte in V5 von modifizierten Zugriff df.

+1

Mögliche Duplikate von [Roll join mit Start/Ende-Fenster] (http://StackOverflow.com/Questions/24480031/Roll-join-With-start-end-window) – zx8754

+0

@ zx8754 Der Unterschied ist in dieser Frage es ist nur eine Zahl, die geprüft wird, ob sie im Bereich existiert oder nicht, ** hier suche ich nach einem Bereich (keine Nummer) mit einem anderen Bereich **. – Newbie

+0

@ zx8754 'newdf <- Teilmenge (merge (Zugriff, Peaks), Start <= V2 & V3 <= Ende)' das gibt mir nur diejenigen, die in diesen Bereich fällt, ich bin nicht in der Lage, herauszufinden, wie Sie ihnen zuweisen Kategorien, die ich definiert habe, und auch, wie man diejenigen hält, die nicht vollständig in diese Bereiche fallen. Kannst du mir dabei helfen..? – Newbie

Antwort

0

Hier ist eine andere (einfache) Lösung, die die Nicht-equi mit implementiert Joins vor kurzem und in der aktuellen Entwicklungsversion von data.table, v1 .9.7. Siehe Montageanleitung here:

require(data.table) # v1.9.7+ 
setDT(access) 
setDT(peaks)[, V4 := "U"]        # no overlap 
peaks[access, V4 := "A", on=.(V1, V2 <= V3, V3 >= V2)] # any overlap 
peaks[access, V4 := "B", on=.(V1, V2 >= V2, V3 <= V3)] # completly within 
#  V1  V2  V3 V4 
# 1: chr10 126122 126533 U 
# 2: chr10 179450 179730 B 
# 3: chr10 182788 183350 A 
# 4: chr10 224244 224500 A 
# 5: chr10 237695 237950 B 

eine neue Spalte peaks hinzufügen, die alle "U" ist. Dann ersetzen Sie die Zeilen, bei denen es irgendeine Art von Überlappung mit "A" gibt. Das würde alle Zeilen enthalten, die auch komplett "innerhalb" sind. Führen Sie dann noch einmal eine bedingte Verknüpfung durch, aber diesmal nur für ganz innerhalb, und ersetzen Sie sie durch "B".


Beachten Sie, dass die foverlaps() Lösung wäre auch gut funktionieren (es kommt auch aus data.table Paket). Aber die neuen Nicht-Equi-Joins passen gut zu der [.data.table-Syntax, die erlaubt, cols zu aggregieren/hinzufügen/zu aktualisieren, während beitreten.

+0

Bitte bestätigen Sie, wenn ich mich nicht irre, sie sind wie folgt: 'peaks [Zugriff, V4: =" A ", on =. (Spitzenwerte $ V1, Spitzenwerte $ V2 <= Zugriff $ V3, Spitzenwerte $ V3> = access $ V2)] 'UND' peaks [Zugriff, V4: = "B", on =. (Peaks $ V1, peaks $ V2> = Zugriff $ V2, peaks $ V3 <= Zugriff $ V3)] ' – Newbie

+0

Sie haben es richtig gemacht. LHS des Ausdrucks bezieht sich auf DT auf der Außenseite. – Arun

+0

Ich habe die Frage geändert, siehe oben Bearbeiten, können Sie mir bitte vorschlagen, wie kann ich dieses neue Problem lösen? Vielen Dank. – Newbie

1

Wenn die Geschwindigkeit wichtig ist, wird die verknüpfte data.table Lösung wahrscheinlich überlegen sein, aber es kann auch in dplyr erreicht werden, aber wahrscheinlich viel langsamer:

library(dplyr) 
names(access)[2:3] <- c('start', 'end') 

bind_cols(peaks[-1], access) %>% 
    rowwise() %>% 
    mutate(V4 = if_else(all(V2:V3 %in% start:end), 'B', 
         if_else(any(V2:V3 %in% start:end), 'A', 
           'U'))) 

Ergebnis:

Source: local data frame [5 x 6] 
Groups: <by row> 

# A tibble: 5 x 6 
     V2  V3  V1 start end V4 
    <int> <int> <fctr> <int> <int> <chr> 
1 126122 126533 chr10 136122 136533  U 
2 179450 179730 chr10 179432 179769  B 
3 182788 183350 chr10 182988 183371  A 
4 224244 224500 chr10 224234 224489  A 
5 237695 237950 chr10 237693 237958  B 
+0

welche Pakete verwenden Sie hier, weil ich folgenden Fehler erhalte: 'Fehler in eval (expr, envir, enclos): konnte die Funktion" if_else "' nicht finden und wenn ich 'ifelse' anstelle von base benutze, bekomme ich mehrere Warnungen und Die Kategorien für alle Zeilen sind ** U ** – Newbie

+0

'dplyr' Version' 0.5.0'. 'if_else' ist nicht in früheren Versionen. – Axeman

+0

Ich habe einen Fehler, wenn ich es auf meine realen Daten anwendete, wo keine Zeilen in 2 Datenrahmen unterschiedlich sind: 'Fehler in eval (expr, envir, enclos): inkompatible Anzahl der Zeilen (103335, erwartet 90)' Can Sie zeigen mir, wie ich dieses Problem lösen kann. – Newbie

1

Obwohl Es ist ein langer Weg, es zu tun. Aber es gibt die gewünschten Ergebnisse.

library(dplyr) 
df<-cbind(peaks,access) #merging both df 
colnames(df)<-c("pV1","pV2","pV3","aV1","aV2","aV3") 
df<-df[c(which(df$pV1==df$aV1)),] # selecting rows with pV1=aV1 
# creating U, A, B 
U1<-df%>% 
    filter(pV2<aV2 & pV3<aV2)%>% 
    mutate(V4="U") 
U2<-df%>% 
    filter(pV2>aV3 & pV3>aV3)%>% 
    mutate(V4="U") 
B<-df%>% 
filter(pV2>aV2 & pV3<aV3)%>% 
    mutate(V4="B") 
A1<-df%>% 
    filter(pV2>aV2 & pV3>aV3)%>% 
    mutate(V4="A") 
A2<-df%>% 
    filter(pV2<aV2 & pV3<aV3 & pV3>aV2)%>% 
    mutate(V4="A") 
#merging U, A and B into newdf 
newdf<-arrange(rbind(U1,U2,B,A1,A2),pV2) 
newdf<-newdf[,-c(4:6)] 
newdf 
    pV1 pV2 pV3 V4 
1 chr10 126122 126533 U 
2 chr10 179450 179730 B 
3 chr10 182788 183350 A 
4 chr10 224244 224500 A 
5 chr10 237695 237950 B 
1

die foverlaps mit der Funktion kann es mit der folgenden Aussage erfolgen:

setkey(setDT(access),V1,V2,V3) 
setkey(setDT(peaks),V1,V2,V3) 

access[,V4:= ifelse(!is.na(foverlaps(peaks, access, type="within", which=TRUE)$yid),"B",ifelse(!is.na(foverlaps(peaks, access, type="any", which=TRUE)$yid),"A","U"))] 

Die Art und Weise funktioniert, ist der folgende:

  1. ich zuerst die „innerhalb“ Art verwenden, um feststellen, ob es eine genaue Überlappung gibt (wenn also ein Bereich in einem der übereinstimmenden Zugriffsbereiche enthalten ist. Wenn dies der Fall ist, dann "B"
  2. Wenn dies nicht der Fall ist, verwende ich das "any", um zu bestimmen, ob es eine Überlappung gibt, die praktisch die Werte identifiziert, die teilweise überlappen, da die Werte mit exakter Überlappung im vorherigen Schritt ausgeschlossen wurden. Diese Werte erhalten ein „A“
  3. Der Rest bekommt ein „U“
+0

Kannst du mir bitte helfen mit dieser [Frage] (http://stackoverflow.com/questions/ 38501840/Datenframeverarbeitung) – Newbie

Verwandte Themen