#r #purrr #read.table #rdata #dat-protocol
#r #purrr #read.table #rdata #dat-протокол
Вопрос:
Я хочу импортировать несколько .DAT
файлов из каталога и сделать их элементами списка, а затем сохранить их как .RDATA
файлы.
Я попробовал следующий код
files <- dir(pattern = "*.DAT")
library(tidyverse)
Data1 <-
files %>%
map(~ read.table(file = ., fill = TRUE))
который иногда работает и не работает в других. Файлы также доступны по этой ссылке . Я хочу прочитать все файлы и сохранить их как .RDATA
с одинаковыми именами.
Комментарии:
1. Вы пробовали
safely
обрабатывать ошибки? Смотрите документы .2. Какие конкретные файлы выходят из строя? Какую ошибку вы получаете? Открывали ли вы файлы, которые не удалось выполнить в редакторе, чтобы посмотреть, имеют ли они структуру, которую вы ожидаете?
3. Я думаю, что более важным стимулом для получения ответов, чем вознаграждение, является предоставление более конкретной информации о том, что «работает иногда и подводит других». В частности, поскольку вы указываете нам на страницу с 510 файлами неизвестного размера, которые нам нужно будет загрузить, чтобы самим увидеть эти детали без четкого описания в вопросе. Сбой чтения файлов? Или их запись?
Ответ №1:
Поскольку данные ссылки частично немного нечисты, я покажу вам решение основной проблемы вашего вопроса на основе этого примера данных:
(name1 <- name2 <- name3 <- name4 <- name5 <- data.frame(matrix(1:12, 3, 4)))
# X1 X2 X3 X4
# 1 1 4 7 10
# 2 2 5 8 11
# 3 3 6 9 12
Мы сохраняем данные в подкаталог вашего рабочего каталога с именем "test"
.
l <- mget(ls(pattern="^name"))
DIR <- "test"
# dir.create(DIR) # leave out if dir already exists
sapply(1:length(l), function(x)
write.table(l[[x]], file=paste0(DIR, "/", names(l)[x], ".dat"), row.names=FALSE))
Теперь посмотрим, что внутри "test"
.
dir(DIR)
# [1] "name1.dat" "name2.dat" "name3.dat" "name4.dat" "name5.dat"
Теперь мы импортируем файлы в каталог по шаблону. Я использую rio::import_list
, который красиво импортирует файлы в список, который используется data.table::fread
внутри. Но ваш собственный код также будет работать нормально.
# rm(list=ls()) # commented out for user safety
L <- rio::import_list(paste0(DIR, "/", dir(DIR, pattern="\.dat$")), format="tsv")
Чтобы сохранить их так, как .Rdata
мы хотим assign
, динамически присваиваем имена, которые мы достигаем с list
помощью опции внутри save()
.
sapply(seq_along(L), function(x) {
tmp <- L[[x]]
assign(names(L)[x], tmp)
save(list=names(L)[x], file=paste0(DIR, "/", names(L)[x], ".Rdata"))
})
Когда мы перечисляем каталог, мы видим, что данные были созданы.
dir(DIR)
# [1] "name1.dat" "name1.Rdata" "name2.dat" "name2.Rdata" "name3.dat" "name3.Rdata"
# [7] "name4.dat" "name4.Rdata" "name5.dat" "name5.Rdata"
Теперь давайте посмотрим, правильно ли были созданы имена объектов:
# rm(list=ls()) # commented out for user safety
load("test/name1.Rdata")
ls()
# [1] "name1"
name1
# X1 X2 X3 X4
# 1 1 4 7 10
# 2 2 5 8 11
# 3 3 6 9 12
Это так.
Дополнительная опция
В качестве альтернативы мы могли бы попробовать более прямой подход, используя rvest
. Сначала мы извлекаем имена данных:
library(rvest)
dat.names <- html_attr(html_nodes(read_html(
"https://www2.stat.duke.edu/courses/Spring03/sta113/Data/Hand/Hand.html"),
"a"), "href")
и создание отдельных ссылок:
links <- as.character(sapply(dat.names, function(x)
paste0("https://www2.stat.duke.edu/courses/Spring03/sta113/Data/Hand/", x)))
Остальное в основном такое же, как указано выше:
DIR <- "test"
# dir.create(DIR) # leave out if dir already exists
library(rio)
system.time(L <- import_list(links, format="tsv") ) # this will take a minute
sapply(seq_along(L), function(x) {
tmp <- L[[x]]
assign(names(L)[x], tmp)
save(list=names(L)[x], file=paste0(DIR, "/", names(L)[x], ".Rdata"))
})
# rm(list=ls()) # commented out for user safety
load("test/clinical.Rdata") # test a data set
clinical
# V1 V2 V3
# 1 26 31 57
# 2 51 59 110
# 3 21 11 32
# 4 40 34 74
# 5 138 135 273
Однако, как отмечалось ранее во введении, данные частично немного нечисты, и вам, вероятно, придется обрабатывать их по отдельности и адаптировать код с учетом регистра.
Комментарии:
1. Спасибо @jay.sf за очень полезный ответ. Спасибо
2. Код
dat.names <- html_attr(html_nodes(read_html( "https://www2.stat.duke.edu/courses/Spring03/sta113/Data/Hand/Hand.html"), "a"), "href")
выдает следующую ошибку:Error in open.connection(x, "rb") : server certificate verification failed. CAfile: /etc/ssl/certs/ca-certificates.crt CRLfile: none
. Любые мысли, пожалуйста.3. Я не могу воспроизвести эту проблему на компьютере с Windows. Возможно, вы захотите попробовать конкретные предложения Linux из этого потока gitlab и сообщить, помогло ли это.
Ответ №2:
Это должно приблизить вас. Он считывает все файлы .dat из вашего каталога и сохраняет их как файлы .RData в вашем каталоге с соответствующими именами. Одним из недостатков является то, что когда вы открываете их в R, они сохраняют имя «temp.file», поэтому вам приходится переименовывать их вручную или просто открывать по одному. Не уверен, как это обойти.
file.list <- lapply(1:length(dir()), function(x) read.delim(dir()[x], header=FALSE))
names.list <- lapply(1:length(dir()), function(x) gsub(".dat", "", dir()[x]))
for(i in 1:length(file.list)){
temp.file <- file.list[[i]]
temp.name <- paste(names.list[[i]], ".RData", sep="")
save(temp.file, file=temp.name)
}