2016-04-28 25 views
0

Ich habe eine Datei, bestehend aus Tausenden von Zeilen dieser Art:R regex Ausdrücke in tidyr und dplyr?

1 number entry size1 size2 value size5 value2 my_id1k "AJKJjsdfe76r55"; my_label “1900”; my_idk2 "49354ytu866"; you_digit "some"; my_copy “jkl”; 
1 number entry size3 size4 value size6 value2 my_id1k "xyz804"; my_id2k “FI71"; my_id3k “Sk9000”; my_id4k “ldv”; 

Ich möchte einen Weg finden, zu extrahieren, was innerhalb der my_id1k und my_id2k Einträge (ohne die Anführungszeichen), sowie Extrakt eingeschlossen ist einige der anderen Spalten (mein Code ist unten angegeben).

Ich möchte die separate() und select() Funktionen in den tidyr und dplyr Pakete für diesen Zweck verwenden, da sie sehr schnell sind (und ich bin besorgt über die Leistung), also habe ich das Studium worden: http://rpackages.ianhowson.com/cran/tidyr/man/separate.html

Allerdings bin ich nicht sicher, wie die into und sep Optionen in dieser Art von heterogenen Fall (wo meine letzte Spalte hat unterschiedliche Länge), um meine gewünschte Ausgabe zu erhalten. Ich habe eindeutig einige Zeilen, die mehr Informationen als andere haben, also frage ich mich, wie ich einen leistungsstarken tidyr und dplyr Code schreiben könnte, der die gewünschten Einträge so schnell wie möglich extrahiert.

Hier ist meine Arbeit so weit:

> library(dplyr) 
> library(tidyr) 
> library(data.table) 
> x <- fread("myfile_MWE.txt") 
> x 
    V1  V2 V3 V4 V5 V6 V7  V8                         V9 
1: 1 number entry size1 size2 value size5 value2 my_id1k "AJKJjsdfe76r55"; my_label “1900”; my_idk2 "49354ytu866"; you_digit "some"; my_copy “jkl”; 
2: 1 number entry size3 size4 value size6 value2         my_id1k "xyz804"; my_id2k “FI71"; my_id3k “Sk9000”; my_id4k “ldv”; 
> y <- separate(x, V9, into = paste("V", 1:15, sep = "_")) 
> y 
    V1  V2 V3 V4 V5 V6 V7  V8 V_1 V_2   V_3 V_4 V_5 V_6 V_7 V_8   V_9 V_10 V_11 V_12 V_13 V_14 V_15 
1: 1 number entry size1 size2 value size5 value2 my id1k AJKJjsdfe76r55 my label 1900 my idk2 49354ytu866 you digit some my copy jkl 
2: 1 number entry size3 size4 value size6 value2 my id1k   xyz804 my id2k FI71 my id3k  Sk9000 my id4k ldv  NA NA 

Offensichtlich aufgrund der unterschiedlichen Länge der letzten Spalte (V9) zeigen einige Einträge als NA, und ich kann nicht erfolgreich managen zu extrahieren, was eingeschlossen ist innerhalb der my_id1k und my_id2k Einträge:

> a <- select(y, V1, V7, V_3, V_9) 
> a 
    V1 V7   V_3   V_9 
1: 1 size5 AJKJjsdfe76r55 49354ytu866 
2: 1 size6   xyz804  Sk9000 
> b <- select(y, V1, V7, V_3, V_6) 
> b 
    V1 V7   V_3 V_6 
1: 1 size5 AJKJjsdfe76r55 1900 
2: 1 size6   xyz804 FI71 

So klar, in einem Fall muß ich V_9 und im anderen Fall, den ich V_6 müssen. Meine gewünschte Ausgabe wäre:

1 size5 AJKJjsdfe76r55 49354ytu866 
1 size6   xyz804 FI71 

Gibt es trotzdem, dass ich die Verwendung von V_9 und V_6 in bedingter Weise angeben kann, so dass der mein Code klug genug zu erkennen, dass ich mag nach unten ziehen, was in der umschlossene ist my_id1k und my_id2k Einträge, zB über reguläre Ausdrücke?

Antwort

1

tidyr::extract ist eine bessere Option als separate oder spread, da es eine Menge von klebrige Masse ist nicht kümmern .

extract(df, V9, c('my_id1k', 'my_id2k'), 'my_id1k .(\\S+).;.*my_id(?:2k|k2) .(\\S+).;') 
# V1  V2 V3 V4 V5 V6 V7  V8  my_id1k  my_id2k 
# 1 1 number entry size1 size2 value size5 value2 AJKJjsdfe76r55 49354ytu866 
# 2 1 number entry size3 size4 value size6 value2   xyz804  FI71 

Hinweis dies setzt voraus, my_id2k und my_idk2 sind die gleichen, wie Sie so viel in der Frage anzunehmen scheinen; my_id1k nicht variiert, so dass die Regex auch nicht. Es wird auch angenommen, my_id1k kommt vor my_id2k. Beachten Sie die Möglichkeiten bei der Erweiterung auf neue Daten und passen Sie die Regex entsprechend an.


Daten:

df <- structure(list(V1 = c(1L, 1L), V2 = structure(c(1L, 1L), .Label = "number", class = "factor"), 
    V3 = structure(c(1L, 1L), .Label = "entry", class = "factor"), 
    V4 = structure(1:2, .Label = c("size1", "size3"), class = "factor"), 
    V5 = structure(1:2, .Label = c("size2", "size4"), class = "factor"), 
    V6 = structure(c(1L, 1L), .Label = "value", class = "factor"), 
    V7 = structure(1:2, .Label = c("size5", "size6"), class = "factor"), 
    V8 = structure(c(1L, 1L), .Label = "value2", class = "factor"), 
    V9 = c("my_id1k \"AJKJjsdfe76r55\"; my_label “1900”; my_idk2 \"49354ytu866\"; you_digit \"some\"; my_copy “jkl”;", 
    "my_id1k \"xyz804\"; my_id2k “FI71\"; my_id3k “Sk9000”; my_id4k “ldv”;" 
    )), .Names = c("V1", "V2", "V3", "V4", "V5", "V6", "V7", 
"V8", "V9"), row.names = c(NA, -2L), class = "data.frame") 
+0

Danke! Ordentlicher Regex. Und in der Tat, danke, dass Sie auf die 'extract()' Funktion hingewiesen haben, war das nicht vertraut! +1! – warship

2

Hier ist die Daten, die ich verwendet:

data = structure(list(V1 = c(1L, 1L), V2 = c("number", "number"), V3 = c("entry", 
"entry"), V4 = c("size1", "size3"), V5 = c("size2", "size4"), 
    V6 = c("value", "value"), V7 = c("size5", "size6"), V8 = c("value2", 
    "value2"), V9 = c("my_id1k \"AJKJjsdfe76r55\"; my_label “1900”; my_idk2 \"49354ytu866\"; you_digit \"some\"; my_copy “jkl”;", 
    "my_id1k \"xyz804\"; my_id2k “FI71\"; my_id3k “Sk9000”; my_id4k “ldv”;" 
    )), .Names = c("V1", "V2", "V3", "V4", "V5", "V6", "V7", 
"V8", "V9"), class = "data.frame", row.names = c(NA, -2L)) 

Und hier ist der Code

library(dplyr) 
library(stringi) 
library(tidyr) 

result = 
    data %>% 
    group_by(V9) %>% 
    do(.$V9 %>% 
     first %>% 
     stri_replace_all_fixed("; ", "\n") %>% 
     read.table(text = ., stringsAsFactors = FALSE)) %>% 
    spread(V1, V2) %>% 
    left_join(data) 
+0

Dank, sehr ähnlich wie Ihre alternative Lösung, vor allem die Nutzung der 'stringi' Bibliothek. +1! – warship

+0

Gute Verwendung von 'do'. Plus eins. – akrun