2016-07-05 11 views
-1

Einer meiner Dateneingänge sieht wie folgt aus:den Index von Strings basiert auf zwei Datenrahmen zu finden

O75663 O95456 O75663 O95456 
O95400 O95670 O95400 O95670 
O95433   O95433 O95801 
       O95456 P00352 
       O95670 

df<- structure(
    list(
     V1 = structure(c(2L, 3L, 4L, 1L, 1L), 
      .Label = c("", "O75663", "O95400", "O95433"), 
       class = "factor"), 
     V2 = structure(c(2L, 3L, 1L, 1L, 1L), 
      .Label = c("", "O95456", "O95670"), 
       class = "factor"), 
     V3 = structure(1:5, 
      .Label = c("O75663", "O95400", "O95433", "O95456", "O95670"), 
       class = "factor"), 
     V4 = structure(c(2L, 3L, 4L, 5L, 1L), 
      .Label = c("", "O95456", "O95670", "O95801", "P00352"), 
       class = "factor")), 
    .Names = c("V1", "V2", "V3", "V4"), 
     class = "data.frame", 
     row.names = c(NA, -5L)) 

Meine zweite Dateneingabe wie folgt aussieht:

O75663 
O95400 
O95433 
O95456 
O95670 
O95801 
P00352 
P00492 

ich für jeden wissen wollen String aus dem zweiten Datensatz, in dem die Spalten der ersten Daten gefunden werden können. Es könnte in keinem von ihnen oder in mehreren sein. Ich möchte die Ausgabe wie folgt aussehen:

strings column ids 
O75663  1, 3 
O95400  1, 3 
O95433  1, 3 
O95456  2, 3, 4 
O95670  2, 3, 4 
O95801  4 
P00352  4 
P00492  NA 

Die neue strs:

strs <- structure(
    list(
     strings = structure(c(2L, 3L, 4L, 5L, 6L, 7L, 1L, 1L), 
      .Label = c("", "O75663", "O95400", "O95433", "O95456", "O95670", "O95801"), 
       class = "factor"), 
     strings2 = structure(c(4L, 2L, 6L, 5L, 3L, 1L, 1L, 1L), 
      .Label = c("", "O75663", "O95433", "O95456", "P00352", "P00492"), 
       class = "factor"), 
     strings3 = structure(c(4L, 6L, 7L, 8L, 2L, 3L, 5L, 1L), 
      .Label = c("", "O75663", "O95400", "O95456", "O95670", "O95801", "P00352", "P00492"), 
       class = "factor"), 
     strings4 = structure(c(2L, 5L, 3L, 4L, 1L, 1L, 1L, 1L), 
      .Label = c("", "O95400", "O95456", "O95801", "P00492"), 
       class = "factor"), 
     strings5 = structure(c(8L, 2L, 7L, 1L, 3L, 6L, 5L, 4L), 
      .Label = c("O75663", "O95400", "O95433", "O95456", "O95670", "O95801", "P00352", "P00492"), 
       class = "factor")), 
    .Names = c("strings", "strings2", "strings3", "strings4", "strings5"), 
     class = "data.frame", 
     row.names = c(NA, -8L)) 


lut <- structure(
    list(
     V1 = c("O75663", "O95400", "O95433", NA, NA), 
     V2 = c("O95456", "O95670", NA, NA, NA), 
     V3 = c("O75663", "O95400", "O95433", "O95456", "O95670"), 
     V4 = c("O95456", "O95670", "O95801", "P00352", NA), 
     V1 = c("O75663", "O95400", "O95433", NA, NA), 
     V2 = c("O95456", "O95670", NA, NA, NA), 
     V3 = c("O75663", "O95400", "O95433", "O95456", "O95670"), 
     V4 = c("O95456", "O95670", "O95801", "P00352", NA)), 
    .Names = c("V1", "V2", "V3", "V4", "V1", "V2", "V3", "V4"), 
    row.names = c(NA, -5L), class = "data.frame") 

df<- setDT(strs)[, paste0('colids_',seq_along(strs)) := 
    lapply(.SD, function(x) toString(which(colSums(lut == x, na.rm=TRUE) > 0))), 
    by = 1:nrow(strs)][] 

Dann bekomme ich diesen Fehler:

Error in df1 == x : comparison of these types is not implemented
In addition: Warning message: In is.data.frame(x) :
Incompatible methods (" Ops.data.frame ", " Ops.factor ") for " == "

Antwort

4

Eine mögliche Lösung mit Base R durch eine Verwendung Kombination von colSums, which, toString und apply:

strs$colids <- apply(strs, 1, function(x) toString(which(colSums(lut == x, na.rm=TRUE) > 0))) 

die gibt:

> strs 
    strings colids 
1 O75663 1, 3 
2 O95400 1, 3 
3 O95433 1, 3 
4 O95456 2, 3, 4 
5 O95670 2, 3, 4 
6 O95801  4 
7 P00352  4 
8 P00492   

Um zu sehen, was jeder Teil hat, beginnen Sie am Ausgang des lut == 'O75663' suchen, die Ihnen eine TRUE/FALSE Tabelle geben. Indem Sie diese in colSums verpacken, addieren Sie die TRUE/FALSE. A 0 bedeutet, dass in dieser Spalte für diese Zeichenfolge keine Übereinstimmung vorhanden ist. Eine Zahl über Null bedeutet, dass mindestens eine Übereinstimmung vorhanden ist. Mit which erhalten Sie die Spaltenindizes, und indem Sie das in umhüllen, erhalten Sie Zeichenwerte mit Indizes der übereinstimmenden Spalten.

Dieser Ansatz auch mit entweder data.table oder dplyr umgesetzt werden könnte:

library(data.table) 
setDT(strs)[, colids := toString(which(colSums(lut == strings, na.rm=TRUE) > 0)), by = 1:nrow(strs)][] 

library(dplyr) 
strs %>% rowwise() %>% mutate(colids = toString(which(colSums(lut == strings, na.rm=TRUE) > 0))) 

Als Antwort auf Ihren Kommentar: Ein Beispiel für mehrere Spalten in strs mit data.table:

# create an extra strings column 
set.seed(1) 
strs$strings2 <- sample(strs$strings) 

# create two 'colids' columns 
library(data.table) 
setDT(strs)[, c('colids1','colids2') := lapply(.SD, function(x) toString(which(colSums(lut == x, na.rm=TRUE) > 0))), by = 1:nrow(strs)][] 

der gibt:

strings strings2 colids1 colids2 
1: O75663 O95433 1, 3 1, 3 
2: O95400 P00492 1, 3   
3: O95433 O95456 1, 3 2, 3, 4 
4: O95456 O95670 2, 3, 4 2, 3, 4 
5: O95670 O75663 2, 3, 4 1, 3 
6: O95801 P00352  4  4 
7: P00352 O95400  4 1, 3 
8: P00492 O95801    4 

Gebrauchte Daten:

lut <- structure(list(V1 = c("O75663", "O95400", "O95433", NA, NA), 
         V2 = c("O95456", "O95670", NA, NA, NA), 
         V3 = c("O75663", "O95400", "O95433", "O95456", "O95670"), 
         V4 = c("O95456", "O95670", "O95801", "P00352", NA)), 
       .Names = c("V1", "V2", "V3", "V4"), class = "data.frame", row.names = c(NA, -5L)) 

strs <- structure(list(strings = c("O75663", "O95400", "O95433", "O95456", "O95670", "O95801", "P00352", "P00492")), 
        .Names = "strings", class = "data.frame", row.names = c(NA, -8L)) 

Im Hinblick auf die erweiterten Beispiel, das Sie zu Ihrer Frage hinzugefügt: Der Grund, warum Sie diesen Fehler erhalten, weil Sie zu vergleichen Faktor- versuchen Variablen mit Zeichenvariablen. Sehen Sie den Unterschied in der Ausgabe zwischen sapply(strs,class) und sapply(lut,class):

> sapply(strs,class) 
strings1 strings2 strings3 strings4 strings5 
"factor" "factor" "factor" "factor" "factor" 
> sapply(lut,class) 
     V1   V2   V3   V4   V5   V6   V7   V8 
"character" "character" "character" "character" "character" "character" "character" "character" 

Es ist daher notwendig, die factor ‚s character‘ s erste und führen Sie dann den Vergleich zu konvertieren.Der folgende Code:

library(data.table) 
setDT(strs)[, lapply(.SD, as.character) 
      ][, paste0('colids.',seq_along(strs)) := lapply(.SD, function(x) toString(which(colSums(lut == x, na.rm=TRUE) > 0))), 
       by = 1:nrow(strs)][] 

gibt jetzt die korrekte Ausgabe:

strings1 strings2 strings3 strings4 strings5   colids.1   colids.2   colids.3   colids.4   colids.5 
1: O75663 O95456 O95456 O95400 P00492  1, 3, 5, 7 2, 3, 4, 6, 7, 8 2, 3, 4, 6, 7, 8  1, 3, 5, 7     
2: O95400 O75663 O95801 P00492 O95400  1, 3, 5, 7  1, 3, 5, 7    4, 8      1, 3, 5, 7 
3: O95433 P00492 P00352 O95456 P00352  1, 3, 5, 7        4, 8 2, 3, 4, 6, 7, 8    4, 8 
4: O95456 P00352 P00492 O95801 O75663 2, 3, 4, 6, 7, 8    4, 8        4, 8  1, 3, 5, 7 
5: O95670 O95433 O75663   O95433 2, 3, 4, 6, 7, 8  1, 3, 5, 7  1, 3, 5, 7      1, 3, 5, 7 
6: O95801   O95400   O95801    4, 8      1, 3, 5, 7        4, 8 
7:      O95670   O95670         2, 3, 4, 6, 7, 8     2, 3, 4, 6, 7, 8 
8:          O95456                  2, 3, 4, 6, 7, 8 

Gebrauchte Daten erweitert Beispiel:

strs <- structure(list(strings1 = structure(c(2L, 3L, 4L, 5L, 6L, 7L, 1L, 1L), .Label = c("", "O75663", "O95400", "O95433", "O95456", "O95670", "O95801"), class = "factor"), 
         strings2 = structure(c(4L, 2L, 6L, 5L, 3L, 1L, 1L, 1L), .Label = c("", "O75663", "O95433", "O95456", "P00352", "P00492"), class = "factor"), 
         strings3 = structure(c(4L, 6L, 7L, 8L, 2L, 3L, 5L, 1L), .Label = c("", "O75663", "O95400", "O95456", "O95670", "O95801", "P00352", "P00492"), class = "factor"), 
         strings4 = structure(c(2L, 5L, 3L, 4L, 1L, 1L, 1L, 1L), .Label = c("", "O95400", "O95456", "O95801", "P00492"), class = "factor"), 
         strings5 = structure(c(8L, 2L, 7L, 1L, 3L, 6L, 5L, 4L), .Label = c("O75663", "O95400", "O95433", "O95456", "O95670", "O95801", "P00352", "P00492"), class = "factor")), 
        .Names = c("strings1", "strings2", "strings3", "strings4", "strings5"), class = "data.frame", row.names = c(NA, -8L)) 

lut <- structure(list(V1 = c("O75663", "O95400", "O95433", NA, NA), 
         V2 = c("O95456", "O95670", NA, NA, NA), 
         V3 = c("O75663", "O95400", "O95433", "O95456", "O95670"), 
         V4 = c("O95456", "O95670", "O95801", "P00352", NA), 
         V5 = c("O75663", "O95400", "O95433", NA, NA), 
         V6 = c("O95456", "O95670", NA, NA, NA), 
         V7 = c("O75663", "O95400", "O95433", "O95456", "O95670"), 
         V8 = c("O95456", "O95670", "O95801", "P00352", NA)), 
       .Names = c("V1", "V2", "V3", "V4", "V5", "V6", "V7", "V8"), row.names = c(NA, -5L), class = "data.frame") 
+0

eine Bitte, hier, dass Sie die Spalten machen [ , c ('colids1', 'colids2') wenn meine Daten riesig sind, dann kann ich das nicht manuell machen, wäre es möglich so viele c zu haben Spalten wie meine Daten mit Namen wie colids1 bis .... – nik

+0

Ich habe versucht, paste0 zu verwenden, aber es brachte mich nicht näher col <- colnames (strs) df <- setDT (strs) [, paste0 (c ('c'), rep (col, each = 1)): = lapply (.SD, Funktion (x) toString (was (colSums (lut == x, na.rm = TRUE)> 0))), durch = 1: nrow (strs)] [] – nik

+0

@nik Angenommen, alle Spalten sind String-Spalten, können Sie 'setDT (strs) [, paste0 ('colids.', Seq_along (strs)): = lapply (.SD, function (x) toString (was (colSums (lut == x, na.rm = TRUE)> 0))), durch = 1: nrow (strs)] [] '. Wenn Sie dies nur für eine bestimmte Gruppe von Spalten tun möchten, können Sie sie mit '.SDcols' wie folgt angeben:' setDT (strs) [, paste0 ('colids.', Seq_along (strs)): = lapply (.SD, function (x) toString (was (colSums (lut == x, na.rm = TRUE)> 0))), durch = 1: nrow (strs), .SDcols = Namen (strs) [1 : 2]] [] ' – Jaap

Verwandte Themen