do.call() неправильно добавляет список кадров данных. есть идеи, почему?

#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 указывает источник каждой строки