2017-12-07 11 views
1

Ich arbeite mit einem großen Datensatz, wo ich feststellen möchte, ob eine Spalte mit Textstrings einen logischen Test besteht, wo ich es später austeilen kann. Derzeit versuche ich, die Testspalte für jede Zeile zu erstellen. Der Test basiert darauf, ob die Zelle weniger als 2 relevante Zeichen enthält, aber ich möchte den vollständigen Satz von Zeichen in der tatsächlichen Zelle behalten. Das folgende ist ein vereinfachtes Beispiel dafür, was ich zu tun versucht:R Wert in einer Spalte ändern, wenn Inhalt in einer anderen Spalte Zeichenfolge enthält

Angenommen, ich habe folgenden Datenrahmen:

df <- data.frame(matrix(NA, nrow = 5, ncol = 1)) 
colnames(df) <- "test" 
df$test <- c("one", "two", "three", "one", "onetwo") 
df$hyp <- ("two", "one", "onetwo", "one", "two") 
df$testcount <- sapply(df$test, str_length) 
df$hypcount <- sapply(df$hyp, str_length) 
df 

    test hyp testcount hypcount 
1 one two   3  3 
2 two one   3  3 
3 three onetwo   5  6 
4 one one   3  3 
5 onetwo two   6  3 

Ich mag eine Textzeichenfolge identifizieren, wie „zwei“, und wenn eine Zeile in der test Spalte oder hyp Spalte (abhängig von dem Test, den ich ausführen. Ich möchte nicht, dass dies auf beiden Spalten ausgeführt wird) enthält die Zeichenfolge (obwohl nicht identisch mit der Zeichenfolge), dann möchte ich die gleiche Zeile zu subtrahieren die Anzahl der Zeichen in der Zeichenfolge, die ich aus den Spalten testcount oder hypcount identifiziert habe.

Zum Beispiel, wenn ich diese Funktion auf der Textzeichenfolge „zwei“ in der Spalte test laufen, dann sollte ich die folgende Ausgabe:

test hyp testcount hypcount 
1 one two   3  3 
2 two one   0  3 
3 three onetwo   5  6 
4 one one   3  3 
5 onetwo two   3  3 

Und wenn ich dies auf der hyp Säule laufen , dann sollte ich folgende Ausgabe bekommen:

test hyp testcount hypcount 
1 one two   3  0 
2 two one   3  3 
3 three onetwo   5  3 
4 one one   3  3 
5 onetwo two   6  0 

Ich habe drei Ansätze ausprobiert. Zuerst habe ich versucht, ein, wenn die Funktion mit dem Ersatz bedingt auszuführen (in diesem Test, den ich für die Zeichenfolge „Eins“ anstelle von „zwei“ getestet):

if(grepl("one", df$test)) { 
    df[which(grepl("one", df$test)), ]$testcount = df[which(grepl("one", df$test)), ]$testcount - 3 
    } 

Aber das gibt die Warnung: „In if (Grepl ("Eins", df $ Test)) {: die Bedingung hat Länge> 1 und nur das erste Element wird verwendet "

Dies führt zu einer korrekten Ersetzung für die Zeichenfolge" eins ", aber nicht die Zeichenfolge" zwei". Wenn ich die Zeichenfolge "zwei" in der Spalte hyp ersetze, funktioniert die Funktion, aber nicht, wenn ich die Ersetzung für die Zeichenfolge "eins" ausführe. Ich vermute, dies ist, weil es nur den Test in der ersten Zeile ausführt, und wenn es wahr ist, dann überprüft es den gesamten Datenrahmen.

Weiter habe ich versucht, die Funktion innerhalb einer lapply Funktion ausgeführt wird:

df <- data.frame(lapply(df, function(x) { 
    if(grepl("one", df$test)) { 
    df[which(grepl("one", df$test)), ]$testcount = df[which(grepl("one", df$test)), ]$testcount - 3 
    }})) 

Dies auch nicht funktioniert, obwohl ich nicht vollständig verstehen, warum. Irgendwie endet die Ausgabe der Rückkehr nach oben:

test hyp testcount hypcount 
1 0 0   0  0 
2 0 0   0  0 
3 3 3   3  3 

Schließlich habe ich versucht, es als ifelse laufenden Betrieb (hier ich zu ersetzen für String geschaltet „zwei“, so glaube ich nicht versehentlich die Funktion auf allen Zeilen funktioniert) :

df$testcount <- ifelse(grepl("two", df$test), (df[which(grepl("two", df$test)), ]$testcount = df[which(grepl("two", df$test)), ]$testcount - 3)) 

Das Merkwürdige ist, das funktionierte, als ich es vor ein paar Tagen zum ersten Mal angewendet habe. Ich habe es für die Strings "zwei", "ein" und "eins" getestet, und es hat richtig funktioniert. Jetzt, als ich dazu kam, es auf meine tatsächlichen Daten anzuwenden, funktionierte es nicht. Außerdem, als ich zum Testen zurückging, um zu sehen, was schief gelaufen ist, funktioniert es nicht mehr.Es gibt einfach den Fehler zurück: "Fehler in ifelse (grepl (" zwei ", df $ test), (df [die (grepl (" zwei ", df $ test)),: Argument" Nein "fehlt, mit kein Standard“

ich habe zwei Lösungen für diese versucht Zuerst habe ich versucht, eine Erklärung in das Hinzufügen.‚nein‘Argument, das keinen Einfluss auf meine Daten haben würde:

df$testcount <- ifelse(grepl("two", df$test), (df[which(grepl("two", df$test)), ]$testcount = df[which(grepl("two", df$test)), ]$testcount - 3), T) 

dies verursacht jedoch, es zu gebe die Ausgabe zurück:

test hyp testcount hypcount 
1 one two   1  3 
2 two one   3  3 
3 three onetwo   1  6 
4 one one   1  3 
5 onetwo two   0  3 

Als nächstes habe ich versucht, ein bedeutungsvolles Nein Argument zu ersetzen :

df$testcount <- ifelse(grepl("two", df$test), (df[which(grepl("two", df$test)), ]$testcount = df[which(grepl("two", df$test)), ]$testcount - 3), (df[which(grepl("two", df$test)), ]$testcount = df[which(grepl("two", df$test)), ]$testcount)) 

Aber jetzt gibt es die Ausgabe:

test hyp testcount hypcount 
1 one two  -3  3 
2 two one   0  3 
3 three onetwo  -3  6 
4 one one   0  3 
5 onetwo two  -3  3 

ich diese Ausgabe nicht verstehen.

Meine Frage ist, kann mir jemand helfen zu verstehen, warum das nicht funktioniert, und bieten eine Lösung? Danke im Voraus!

+0

„Ich möchte, dass in derselben Zeile die Anzahl der Zeichen in der Zeichenkette I identifiziert abzuziehen“. In Ihrem ersten Beispiel enthält 'onetwo' die Zeichenkette' two', also sollten Sie nicht 6 (die Länge von 'onetwo') von' testcount = 6' subtrahieren, um die Null zu erhalten? – neilfws

+0

OK, ich sehe aus Ihrem Kommentar unten, dass "die Zeichenfolge" die Übereinstimmungszeichenfolge (zwei) ist, nicht die übereinstimmende Zeichenfolge (onetwo). – neilfws

Antwort

0

Versuchen Sie, diese Funktion:

subtract_match <- function(column1, column2, text, df) { 
    df2 <- df 
    df2[, column2] <- ifelse(grepl(text, df[, column1]), 
          df[, column2] - nchar(text), 
          df[, column2]) 
    df2 
} 

subtract_match("test", "testcount", "two", df1) 

    test hyp testcount hypcount 
1 one two   3  3 
2 two one   0  3 
3 three onetwo   5  6 
4 one one   3  3 
5 onetwo two   3  3 

subtract_match("hyp", "hypcount", "two", df1) 

    test hyp testcount hypcount 
1 one two   3  0 
2 two one   3  3 
3 three onetwo   5  3 
4 one one   3  3 
5 onetwo two   6  0 
+0

Das hat funktioniert! Vielen Dank. Außerdem kann ich das Herz der Funktion herausziehen und es sollte schneller laufen, da es kein Funktionsaufruf mehr sein wird. 'df $ testcount <- ifelse (grepl (" zwei ", df $ test), df $ testcount - nchar (" zwei "), df $ testcount)' Es ist lustig, mein dritter Ansatz war sehr nah an der Lösung ... Danke nochmal! – micheal6126

0

Ich bin mir nicht sicher, ob ich Ihr Problem vollständig verstehe, aber das folgende reproduziert Ihr erwartetes Ergebnis für die beiden Testfälle.

# The first argument is the column where you want to find id 
# I'm unsure about what you want to subtract; subtracting the entry from 
# the count columns corresponds to setting the entry to 0 
some_function <- function(col, id, df) { 
    idx <- which(colnames(df) == col); 
    df[df[, idx] == id, idx + 2] <- 0; 
    return(df); 
} 

some_function("test", "two", df); 
# test hyp testcount hypcount 
#1 one two   3  3 
#2 two one   0  3 
#3 three onetwo   5  6 
#4 one one   3  3 
#5 onetwo two   6  3 

some_function("hyp", "two", df) 
# test hyp testcount hypcount 
#1 one two   3  0 
#2 two one   3  3 
#3 three onetwo   5  6 
#4 one one   3  3 
#5 onetwo two   6  0 

Auch sagen Sie „die Zeichenfolge enthält (obwohl auf den String nicht identisch ist)“, aber für Einträge mit „onetwo“ Sie tun nicht die Zählwerte subtrahieren. Also sind es komplette Matches, nach denen du suchst?

+0

Entschuldigung, diese Funktion erkennt nicht, dass der String "two" in Zeile fünf der "test" -Spalte ist, und ändert den Wert in Zeile fünf der "testcount" -Spalte auf 3. Ziel ist es, alle zu identifizieren Instanzen einer Textzeichenfolge in der Spalte "test" und subtrahieren die Länge dieses Texts (drei im Fall der Zeichenfolge "zwei") Zeichenfolge aus dem Wert in der Spalte "testcount". Hilft das? – micheal6126

Verwandte Themen