2016-08-15 4 views
2

Da ist eine Zeichenfolge mit einer (einzelnen) Nummer irgendwo drin. Ich möchte die Nummer um eins erhöhen. Einfach, oder? Ich schrieb das folgende, ohne es einen zweiten Gedanken zu geben:Inkrementieren einer Zahl in einer Zeichenfolge mit Sub

sub("([[:digit:]]+)", as.character(as.numeric("\\1")+1), string) 

... und bekam eine NA.

> sub("([[:digit:]]+)", as.character(as.numeric("\\1")+1), "x is 5") 
[1] NA 
Warning message: 
In sub("([[:digit:]]+)", as.character(as.numeric("\\1") + 1), "x is 5") : 
    NAs introduced by coercion 

Warum funktioniert es nicht? Ich kenne andere Möglichkeiten, dies zu tun, also brauche ich keine "Lösung". Ich möchte verstehen, warum diese Methode fehlschlägt.

+0

Kann nicht ohne eine Rückruffunktion der Gsub-Funktion arbeiten. Die Alternative besteht darin, die Zeichenfolge in einer Schleife mit einem globalen _search_ neu zu schreiben. – sln

+0

Im Grunde genommen wird der _substitute_ string-Teil von gsub als Vorlage mit zurückreferentiellen Variablen verwendet, die durch einen _internal_ Callback formatiert werden (normalerweise nicht verfügbar). Also, Sie können Code innerhalb dieses Teils der Funktion nicht wirklich ausführen, sogar mit bösen eval (die nichts von der Übereinstimmung wissen). – sln

Antwort

3

Der Punkt ist, dass die Rückreferenz nur während einer Match-Operation ausgewertet wird, und Sie können es nicht an eine Funktion vorher übergeben.

Wenn Sie as.numeric("\\1") die as.numeric Funktion schreiben akzeptiert eine \1 Zeichenfolge (ein Backslash und ein 1 char). Somit wird das Ergebnis erwartet, NA.

Dies geschieht, weil es keine integrierte in Rückreferenzierung Interpolation in R. ist

Sie ein gsubfn Paket verwenden:

> library(gsubfn) 
> s <- "x is 5" 
> gsubfn("\\d+", function(x) as.numeric(x) + 1, s) 
[1] "x is 6" 
+1

Ah, natürlich - as.numeric wird zuerst ausgewertet. Danke für die Einsicht. (Und danke an AEF und Laurel für ihre Antworten!) –

2

Es funktioniert nicht, weil die Argumente von sub ausgewertet werden, bevor sie an die Regex-Engine übergeben werden (die von .Internal aufgerufen wird).

Insbesondere as.numeric("\\1") ergibt NA ... danach bist du verloren.

2

Es könnte einfacher sein, es anders zu denken. Sie haben die gleichen Fehler, die Sie erhalten würden, wenn Sie verwendet:

print(as.numeric("\\1")+1) 

Denken Sie daran, werden die Saiten an die Funktion übergeben, wo sie von der Regex-Engine interpretiert werden. Die Zeichenkette \\1 wird nie in 5 umgewandelt, da diese Berechnung innerhalb der Funktion erfolgt.

Beachten Sie, dass \\1 nicht etwas ist, das als Nummer funktioniert. NA scheint in anderen Sprachen zu null ähnlich zu sein:

NA ... ein Produkt des Betriebes ist, wenn Sie versuchen, etwas zugreifen, die

Von mpiktas' Antwort here nicht da ist.

+0

R hat auch 'NaN'. "NA" und "NaN" sind ähnlich, aber nicht identisch. –

+0

@BenBolker Danke für die Info! Ich weiß nicht viel R, aber ich bin bereit zu lernen. NA scheint in einigen Sprachen ähnlicher zu sein. – Laurel

+0

https://cran.r-project.org/doc/manuals/r-release/R-intro.html # Fehlende Werte –

Verwandte Themen