2015-07-23 8 views
9

Wenn ich tue:Wie Zeichenvektor in file.path in R zu indizieren

file.path("", "a", "b", "c.txt") 
[1] "https://stackoverflow.com/a/b/c.txt" 

bekam ich den richtigen Dateipfad, aber wenn ich auf diese Weise tun:

cc<-c("", "a", "b", "c.txt") 
file.path(cc) 
[1] ""  "a"  "b"  "c.txt" 

Es scheint falsch. Ich frage mich, wie man cc in file.path() indexieren kann?

+3

'do.call ('file.path', as.list (cc))' – rawr

Antwort

10

Ich denke, man der Argumente dieses eine Liste nennen könnte und nicht nur eine einzige. Zum Beispiel können Sie jedes Element der Punkte zuzugreifen:

f <- function(...) { 
    list(one = ..1, 
     three = ..3, 
     four = ..4, 
     two = ..2) 
} 
f(1, 2, 3, 4) 

# $one 
# [1] 1 
# 
# $three 
# [1] 3 
# 
# $four 
# [1] 4 
# 
# $two 
# [1] 2 

Aber was Sie wirklich wollen, ist zu tun passieren jeweils als einzelne Argumente. Also in diesem Fall, müssen Sie entweder das tun explizit (viele Typisierung) oder do.call verwenden, die eine Liste von Parametern Funktionen

cc <- c("", "a", "b", "c.txt") 
do.call('file.path', as.list(cc)) 
# [1] "https://stackoverflow.com/a/b/c.txt" 

file.path passieren lässt ist schön, dass es nur zwei Argumente, ein von denen brauchen Sie nicht zu ändern, aber wenn Sie hast du

do.call('file.path', c(as.list(cc), fsep = '/xx/')) 
# [1] "/xx/a/xx/b/xx/c.txt" 

so in diesem Fall tun könnten Sie eine namens Liste an die Funktion zu übergeben jedes Argument entsprechen

Eine Randnotiz, die ich über gekommen sind, so etwas wie

do.call('base::mean', list(1:4)) 
# Error in do.call("base::mean", list(1:4)) : 
# could not find function "base::mean" 

funktioniert nicht, wenn Sie eine Funktion in einem bestimmten Paket angeben müssen. Sie entweder

f <- base:::mean; do.call('f', list(1:4)) 
# [1] 2.5 

oder nur

do.call(base::mean, list(1:4)) 
# [1] 2.5 
+1

Interessanterweise funktioniert 'do.call (base ::" mean ", liste (1: 4)), aber hoffentlich würde das niemand tun. –

+0

'do.call' erwartet nicht, sein erstes Argument zu analysieren, aber wenn es zuerst zu einem Funktionsnamen ausgewertet wird, akzeptiert es es, da es eine nicht standardisierte Auswertung vornimmt. –

+0

@BondedDust Ich sehe .. Ich dachte Parsing wäre "sicherer" in der gleichen Weise, die 'Bibliothek ('x')' ist "sicherer" als 'Bibliothek (x)' – rawr

3

Sie können stattdessen paste mit collapse="/" verwenden. So mit:

cc <- c("", "a", "b", "c.txt") 

Sie erhalten:

R> paste(cc, collapse="/") 
[1] "https://stackoverflow.com/a/b/c.txt" 
+0

Der Grund, warum ich file.path verwenden () Vermeiden Sie die Verwendung von paste(). –

+1

file.path() kann den Unterschied zwischen Plattformen wie Windows und Mac erkennen. –

+0

Okay, ich verstehe. Dann ist der obige Kommentar von rawr eine viel bessere Lösung. – christoph

5

Ich wollte schreiben das gleiche wie rawr die akzeptierte Antwort/Kommentar tun müssen (so entschieden ein bisschen mehr hinzuzufügen, nachdem auf ihn wartete eine Antwort schreiben und dann warten aufgeben obwohl ich, dass er jetzt sehen, eine Antwort hat):

do.call('file.path', as.list(cc)) 

Learning as.list zu bedienen und do.call wurde einer dieser Lektionen lernte ich einige Jahre tun Wn der Weg zu meiner aktuellen ewigen Zwischenstufe R Meisterschaft. Der Grund, dass die Antwort von rawr funktioniert, ist, dass die Argumente zu file.path als Argument in die args-Komponente der Funktion kommen müssen. Der Grund dafür, dass sie einfach mit list(), z. B. file.path(list(cc)), umbrochen wird, besteht darin, dass das Ergebnis eine Liste der Länge eins ist, während die as.list-Funktion eine Liste der Länge-4 erstellt. Der Grund dafür, dass file.path(as.list(cc)) ebenfalls fehlschlägt, besteht darin, dass der Parser dieses Argument immer noch als einen einzelnen Vektor durchläuft.

Manchmal do.call ist der einzige Weg, um eine Funktion call, wenn die Argumentwerte geliefert zu einem ... (Punkten) Bestandteil einer Funktion, sondern existieren in einem anderen Daten-Objekt zu gehen, zu bauen. Wenn mit dem Namen Argumente an eine Funktion kann man entweder Listen oder pairlists verwenden:

> dd <- list(from=1, to=2) 
> seq(dd) 
[1] 1 2 
Verwandte Themen