2016-08-19 3 views
2

OK verloren, ich habe ein kleines Problem, das ich glaube, dass ich mit which und grepl lösen kann (Alternativen sind willkommen), aber ich bin verloren:zu verwenden, die() und regex in R

my_query<- c('g1', 'g2', 'g3') 
my_data<- c('string2','string4','string5','string6') 

Ich möchte den Index in my_query passend in my_data zurückgeben. Im obigen Beispiel ist nur 'g2' in mydata, also wäre das Ergebnis in diesem Beispiel 2. Bitte helfen Sie :)

+1

Einige Ideen: 'sapply (meine_Abfrage, grepl, x = meine_Daten)', 'sapply (meine_Abfrage, grepl, x = meine_Daten)'. Du könntest den zweiten in 'which()' einpacken. – Gregor

+0

Danke, Gregor. Ich denke, die 2 Beispiele sind identisch.Außerdem gibt es mir eine Matrix zurück, wie du sagst, ich würde es so einwickeln müssen, um die Spaltennummer der Matrix zu erhalten. Ich denke, – madmaxthc

+1

Entschuldigung, meinte der zweite sei "sapply" (my_query, function (q) any (grepl (q, my_data))) '', was zu 'what (sapply (my_query, function (q) any (grepl (q, my_data))) 'führt. Aber mehr oder weniger was Zheyuan gepostet hat. – Gregor

Antwort

5

Es scheint mir, dass es keinen einfachen Weg gibt, dies ohne eine Schleife zu tun. Für jedes Element in my_query, können wir eine der folgenden Funktionen verwenden, um TRUE oder FALSE zu erhalten:

f1 <- function (pattern, x) length(grep(pattern, x)) > 0L 

f2 <- function (pattern, x) any(grepl(pattern, x)) 

Zum Beispiel

f1(my_query[1], my_data) 
# [1] FALSE 
f2(my_query[1], my_data) 
# [1] FALSE 

Dann verwenden wir *apply Schleife anwenden, sagen f2 allen Elemente von my_query:

which(unlist(lapply(my_query, f2, x = my_data))) 
# [1] 2 

Danke, das scheint zu funktionieren. Um ehrlich zu sein, habe ich Ihre Originalversion bevorzugt. Ich bin mir nicht sicher, warum Sie mit dem Erstellen einer anderen Funktion bearbeitet haben, um anschließend mit *apply aufzurufen. Gibt es einen Vorteil gegenüber which(lengths(lapply(my_query, grep, my_data)) > 0L)?

Nun, ich bin mir nicht ganz sicher. Als ich ?lengths lesen:

One advantage of ‘lengths(x)’ is its use as a more efficient 
version of ‘sapply(x, length)’ and similar ‘*apply’ calls to 
‘length’. 

Ich weiß nicht, wie viel effizienter, dass lengths mit sapply verglichen wird. Wenn es immer noch eine Schleife ist, führt mein ursprünglicher Vorschlag which(lengths(lapply(my_query, grep, my_data)) > 0L) 2 Schleifen durch. Mein Edit besteht im Wesentlichen aus zwei Loops, die hoffentlich einen Boost bekommen (wenn auch nicht zu klein).

Sie können immer noch mein neues bearbeiten in einer einzigen Zeile anordnen:

which(unlist(lapply(my_query, function (pattern, x) any(grepl(pattern, x)), x = my_data))) 

oder

which(unlist(lapply(my_query, function (pattern) any(grepl(pattern, my_data))))) 
+0

Danke, Zheyuan Li, das scheint zu funktionieren. Um ehrlich zu sein, habe ich deine originale One-Liner-Version bevorzugt;) Ich bin mir nicht sicher, wieso du mit dem Erstellen einer anderen Funktion bearbeitet hast, um danach mit * apply anzurufen. Gibt es einen Vorteil im Vergleich zu "which (lapply (my_query, grep, my_data))> 0)"? – madmaxthc

2

auf einen Kommentar erweitern posted ursprünglich von @Gregor Sie könnten versuchen:

which(colSums(sapply(my_query, grepl, my_data)) > 0) 
#g2 
# 2 

Die Funktion colSums ist vektorisiert und stellt kein Problem in Bezug auf die Leistung dar. Die Schleife sapply() scheint hier unvermeidlich, da wir jedes Element innerhalb des Abfragevektors überprüfen müssen. Das Ergebnis der Schleife ist eine logische Matrix, wobei jede Spalte ein Element von my_query und jede Zeile ein Element von my_data darstellt. Indem wir diese Matrix in which(colSums(..) > 0) einschließen, erhalten wir die Indexnummern aller Spalten, die mindestens eine TRUE enthalten, d. H. Eine Übereinstimmung mit einem Eintrag von my_data.

+0

Nun, Sie können 'sapply' vermeiden durch:' r = regexpr (einfügen (my_query, collapse = "|"), my_data); Übereinstimmung (Regmatches (my_data, r), my_query) ' – Frank

+0

@Frank Interessant. Danke, dass Sie auf diese Möglichkeit hingewiesen haben. Ich persönlich finde es etwas zu kompliziert, aber es ist wahr, dass dort keine Schleife benutzt wird. Zumindest habe ich eine vorsichtige Formulierung verwendet ("... scheint unvermeidlich"), aber ich hätte erkennen müssen, dass es bei der Codierung immer Alternativen gibt. In einer anderen Antwort gab es Diskussionen über eine ähnliche Lösung über verschachtelte Schleifen (wegen der impliziten Schleife innerhalb von "Längen"). In diesem Sinne sieht "colSums" in Kombination mit "grepl" wie eine gute Alternative zu mir aus. – RHertel

+2

Ja, ich würde Ihren Ansatz hier verwenden, denke ich, vor allem, weil ich mich nicht gerne an Regex-Tricks lehne. – Frank