2011-01-17 2 views
3

Надеюсь, что я могу объяснить свой вопрос достаточно хорошо, чтобы получить ответ - любая помощь будет оценена.Вопрос о петле в R

У меня есть число, если файлы данных, которые мне нужно объединить в один. Я использую цикл for для этого и добавляю столбец, который указывает, какой файл он есть.

В этом случае в каждом файле имеется до 6 файлов с до 100 записей данных.

Когда есть 6 файлов, у меня нет проблем с этим.

Но когда есть меньше, у меня есть проблема.

Что я хотел бы сделать, это использовать цикл for для проверки файлов и использовать переменную for loop для сборки вектора, который ссылается на существующие файлы.

Я не могу заставить новую переменную комбинировать новое значение переменной цикла for, поскольку она проходит через цикл.

Вот пример кода, который я написал до сих пор.

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

То, что я ищу, что files_found будет содержать те файлы, в которых 1 ... 6 действительны для найденных файлов.

С уважением Стив

ответ

4

Там в гораздо более короткий способ сделать это с помощью list.files(), как показал Henrik. Если вы не знакомы с регулярными выражениями (см. ?regex), вы можете это сделать.

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

который совершенно эквивалентен. Оба paste и file.exists являются векторизованными функциями, поэтому вам лучше использовать это. Нет необходимости в петле.

Чтобы получить количество имен файлов (при условии, что это только цифры), вы можете сделать:

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

Смотрите также ?regex

+1

Да, я согласен, что векторизованная версия 'file.exists' намного красивее, чем for-loop. Но, с моей точки зрения, 'list.files()' еще приятнее, поскольку у вас есть все в одной строке ... (тем не менее +1) – Henrik

+0

Спасибо за ответы –

+0

Да SampleName и FileName являются строками. Одна маленькая точка, мне бы хотелось получить номер, связанный с каждым найденным файлом, так как мне нужно добавить столбец в файл с этим номером для всех записей в этом файле. Есть идеи? –

3

Я думаю, что есть лучшие решения (например, вы можете использовать list.files() сканировать папку, а затем цикл по длине возвращаемого объекта), но это должно (я не пробовал) сделать трюк (используя образец кода):

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) 
} 

в качестве альтернативы, вы можете получить FileNames (кроме их индекса) через:

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) 
} 

Наконец, в вашем случае list.files может выглядеть примерно так:

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

+1 для списка. файлы –

+0

+1 для указателя 'list.files()' и регулярного выражения. В regexp 'SampleName' и' FileName' были не литералами, а строками в объектах R, по крайней мере, это было мое чтение Q. –

+1

@ Gavin мое чтение тоже. Возможно, я должен уточнить, что 'SampleName' и' FileName' должны быть заменены их значениями и не могут быть переменными. – Henrik

7

Вероятно, было бы лучше, чтобы перечислить файлы, которые вы хотите загрузить , а затем прокрутите список, чтобы загрузить их. list.files - ваш друг здесь. Мы можем использовать регулярное выражение для перечисления только тех файлов, которые заканчиваются на "_Stats.csv".Например, в моем текущем рабочем каталоге у меня есть следующие файлы:

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

Только три из них CSV-файлы, которые я хочу, чтобы загрузить (файл .txt не соответствует шаблону вы показали). Мы можем получить эти имена файлов с помощью list.files():

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

Вы можете перебираем, что и читать файлы в что-то вроде:.

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

Это создаст ряд объектов file_1, file_2, file_3 и т. д. в глобальной рабочей области. Если вы хотите, чтобы файлы в списке, вы могли бы вместо того, чтобы lapply над fnames:

lapply(fnames, read.csv) 

и если подходит, do.call может помочь объединить файлы из списка:

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

+1 для lapply и do.call –

+1

list.files + grep + lapply + do.call - выигрышная комбинация в моей книге. –

Смежные вопросы