2011-01-17 23 views
3

Ich hoffe, ich kann meine Frage gut genug erklären, um eine Antwort zu erhalten - jede Hilfe wird geschätzt.For loop Frage in R

Ich habe eine Nummer, wenn Datendateien, die ich zu einer zusammenführen muss. Ich benutze dafür eine for-Schleife und füge eine Spalte hinzu, die angibt, um welche Datei es sich handelt.

In diesem Fall gibt es 6 Dateien mit jeweils bis zu 100 Dateneinträgen.

Wenn es 6 Dateien gibt, habe ich kein Problem, dies zu erreichen.

Aber wenn es weniger gibt, habe ich ein Problem.

Was ich tun möchte, ist die for-Schleife, um für die Dateien zu testen und die for-Schleife-Variable zum Zusammenstellen eines Vektors, der die vorhandenen Dateien verweist.

Ich kann nicht scheinen, die neue Variable zu erhalten, um den neuen Wert der for-Schleife-Variable zu kombinieren, wie es durch die Schleife geht.

Hier ist der Beispielcode, den ich bisher geschrieben habe.

for (rloop1 in 1 : 6) { 
ReadFile=paste(rloop1,SampleName,"_",FileName,"_Stats.csv", sep="") 
if (file.exists(ReadFile)) 
**files_found <- c(rloop1)** 
} 

Was ich suche, ist, dass files_found diese Dateien enthalten, wobei 1 ... 6 gelten für die gefundenen Dateien.

Grüße Steve

Antwort

4

Es gibt einen viel kürzeren Weg dies mit list.files zu tun() als Henrik zeigte. Falls Sie mit regulären Ausdrücken nicht vertraut sind (siehe ?regex), könnten Sie das tun.

n <- 6 
Fnames <- paste(1:n,SampleName,"_",FileName,"Stats.csv",sep="") 
Filelist <- Fnames[file.exists(Fnames)] 

das ist vollkommen gleichwertig. Sowohl paste als auch file.exists sind vektorisierte Funktionen, die Sie besser nutzen sollten. Es gibt keinerlei Notwendigkeit für eine Schleife.

Um die Anzahl der Dateinamen zu erhalten (unter der Annahme, dass die nur Ziffern ist), können Sie tun:

gsub("^[:digit:]","", Filelist) 

Siehe auch ?regex

+1

Ja, ich stimme zu, dass die vektorisierte Version von 'file.exists' viel hübscher ist als die for-Schleife. Aber von meinem Punkt aus ist 'list.files()' noch netter, da Sie alles in einer Zeile haben ... (nichtsdestotrotz +1) – Henrik

+0

Danke für die Antworten –

+0

Ja SampleName und FileName sind Strings. Ein kleiner Punkt, ich hätte gerne die Nummer erhalten, die jeder gefundenen Datei zugeordnet ist, da ich eine Spalte zu der Datei mit dieser Nummer für alle Datensätze in dieser Datei hinzufügen muss. Irgendwelche Ideen? –

3

Ich denke, es gibt bessere Lösungen (zB könnten Sie list.files() verwenden Sie den Ordner und dann die Schleife über die Länge des zurückgegebenen Objekts zu scannen), aber dies sollte (ich habe nicht versucht, es) den Trick tun (Ihr Beispielcode verwendet wird):

files.found <- ""  
for (rloop1 in 1 : 6) { 
    ReadFile=paste(rloop1,SampleName,"_",FileName,"_Stats.csv", sep="") 
    if (file.exists(ReadFile)) files_found <- c(files.found, rloop1) 
} 

Alternativ Sie die Dateinamen (außer ihrem Index bekommen konnte) über:

files.found <- ""  
for (rloop1 in 1 : 6) { 
    ReadFile=paste(rloop1,SampleName,"_",FileName,"_Stats.csv", sep="") 
    if (file.exists(ReadFile)) files_found <- c(files.found, ReadFile) 
} 

Schließlich in Ihrem Fall list.files könnte wie folgt aussehen:

files.found <- list.files(pattern = "[[:digit:]]_SampleName_FileName_Stats.csv") 
+0

+1 für die Liste. Dateien –

+0

+1 für die 'list.files()' Zeiger und die Regexp. In der Regexp waren 'SampleName' und' FileName' keine Literale, sondern Zeichenketten in R-Objekten, zumindest war dies das Lesen der Q. –

+1

@Gavin meine Lesung. Vielleicht sollte ich klarstellen, dass 'SampleName' und' FileName' durch ihre Werte ersetzt werden sollten und keine Variablen sein dürfen. – Henrik

7

Es wäre wahrscheinlich besser, die Dateien, die Sie laden möchten, zur Liste und dann über diese Liste, um sie zu laden. list.files ist dein Freund hier. Wir können einen regulären Ausdruck verwenden, um nur die Dateien aufzulisten, die auf "_Stats.csv" enden.Zum Beispiel in meinem aktuellen Arbeitsverzeichnis habe ich die folgenden Dateien:

$ ls | grep Stats 
bar_Stats.csv 
foobar_Stats.csv 
foobar_Stats.csv.txt 
foo_Stats.csv 

Nur drei von ihnen sind CSV-Dateien I laden möchten (die .txt Datei nicht mit dem Muster, das Sie zeigte). Wir können diese Dateinamen list.files() erhalten:

> list.files(pattern = "_Stats.csv$") 
[1] "bar_Stats.csv" "foo_Stats.csv" "foobar_Stats.csv" 

Sie können dann eine Schleife über das und lesen Sie die Dateien in so etwas wie:.

fnames <- list.files(pattern = "_Stats.csv$") 
for(i in seq_along(fnames)) { 
    assign(paste("file_", i, sep = ""), read.csv(fnames[i])) 
} 

, die eine Reihe von Objekten file_1, file_2, schaffen file_3 usw. im globalen Arbeitsbereich. Wenn Sie die Dateien in einer Liste möchten, können Sie stattdessen lapply über die fnames:

lapply(fnames, read.csv) 

und geeignet, wenn, könnte do.call helfen, die Dateien aus der Liste kombinieren:

do.call(rbind, lapply(fnames, read.csv)) 
+3

+1 für die Lapply und do.call –

+1

list.files + grep + lapply + do.call ist eine gewinnbringende Kombination in meinem Buch. –