#r #do.call
Вопрос:
Я загружаю множество наборов данных PiT и пытаюсь автоматизировать их объединение в единый фрейм данных временных рядов (master_df).
temp <- tempfile()
testing <- download.file("https://data.sa.gov.au/data/dataset/3ba1c4dd-e52f-4c28-858a-21284c3ee458/resource/c78fc6da-baa4-47cc-b4df-a97f452bbf9a/download/ken01_p.zip",temp)
filenames<-unzip(temp,list=TRUE)[,1]
#only want csvs
filenames<-filenames[str_detect(filenames,".csv")]
dfnames = list()
for (i in 1:length(filenames)){
conn<-unz(temp, filenames[i])
#name files in loop
filename <- sprintf("df_%s",filenames[i] %>%
str_replace("KEN01_p/KEN01p_1hr","") %>%
str_replace(".csv",""))
# list of filenames
dfnames[[i]] <- filename
assign(filename, read.csv(conn))
}
master_df <- do.call(rbind, dfnames)
unlink(temp)
class(master_df)
class(df_201912)
класс(master_df)
[1] «матрица»
класс(df_201912)
[1] «данные.фрейм»
цикл успешно считывает все наборы данных и переименовывает их в df_yyyymm, но do.call rbind просто создает список имен данных.
Что я делаю не так?
Спасибо!!
Ответ №1:
Нет необходимости использовать assign
, так как он записывает все кадры данных в глобальную среду, что не требуется. Вы можете объединить все фреймы данных в одном использовании lapply
, также некоторые фреймы данных имеют разные имена столбцов, поэтому, возможно, будет лучше использовать map_df
их для объединения в один фрейм данных в любом случае путем добавления NA
значений.
purrr::map_df(filenames, function(x) {
read.csv(unz(temp, x))
}) -> master_df
master_df
Ответ №2:
Проблема в коде заключается в присвоении list
элементу имени файла вместо значения
for (i in 1:length(filenames)){
conn<-unz(temp, filenames[i])
#name files in loop
filename <- sprintf("df_%s",filenames[i] %>%
str_replace("KEN01_p/KEN01p_1hr","") %>%
str_replace(".csv",""))
# list of filenames
dfnames[[i]] <- read.csv(conn) ###
#assign(filename, read.csv(conn))
}
Кроме того, есть некоторые list
элементы с разными именами, поэтому rbind
они не будут работать, мы можем использовать rbindlist
из data.table
library(data.table)
out <- rbindlist(dfnames, fill = TRUE) dim(out)
[1] 44544 6
Ответ №3:
Это то, что я бы сделал, чтобы загрузить zip-файл, распаковать его и прочитать все csv-файлы в один большой набор данных:
temp <- tempfile()
testing <- download.file(
"https://data.sa.gov.au/data/dataset/3ba1c4dd-e52f-4c28-858a-21284c3ee458/resource/c78fc6da-baa4-47cc-b4df-a97f452bbf9a/download/ken01_p.zip",
temp)
filenames <- unzip(temp, list = FALSE)
library(data.table)
library(magrittr) # piping used to improve readability
master_df <- lapply(filenames, fread) %>%
set_names(filenames %>% basename() %>% stringr::str_remove_all("^KEN01p_1hr|\.csv$")) %>%
rbindlist(fill = TRUE, idcol = TRUE)
master_df
.id Date/Time PM10 TEOM ug/m3 PM2.5 TEOM ug/m3 Temperature Deg C Barometric Pressure atm PM10 BAM ug/m3 1: 201501 1/01/2015 1:00 18.2 NA 16.8 0.986 NA 2: 201501 1/01/2015 2:00 20.3 NA 15.9 0.985 NA 3: 201501 1/01/2015 3:00 27.9 NA 15.1 0.985 NA 4: 201501 1/01/2015 4:00 23.6 NA 16.9 0.984 NA 5: 201501 1/01/2015 5:00 15.8 NA 19.7 0.984 NA --- 44540: 201912 31/12/2019 20:00 NA NA 19.4 NA 14 44541: 201912 31/12/2019 21:00 NA NA 18.0 NA 14 44542: 201912 31/12/2019 22:00 NA NA 16.7 NA 19 44543: 201912 31/12/2019 23:00 NA NA 15.8 NA 11 44544: 201912 1/01/2020 0:00 NA NA 15.3 NA 12
Обратите внимание, что я изменил list
параметр в
filenames <- unzip(temp, list = FALSE)
Для FALSE
. Это распаковывает zip-файл в подкаталог с именем KEN01_p
. После распаковки подкаталог содержит 61 csv-файл общим объемом 1,5 Мбайт.
Также обратите внимание, что .id
столбец в master_df
указывает источник каждой строки