web-dev-qa-db-fra.com

Quel est le problème avec ma fonction pour charger plusieurs fichiers .csv dans une seule trame de données dans R à l'aide de rbind?

J'ai écrit la fonction suivante pour combiner 300 fichiers .csv. Le nom de mon répertoire est "specdata". J'ai fait les étapes suivantes pour l'exécution,

x <- function(directory) {     
    dir <- directory    
    data_dir <- paste(getwd(),dir,sep = "/")    
    files  <- list.files(data_dir,pattern = '\\.csv')    
    tables <- lapply(paste(data_dir,files,sep = "/"), read.csv, header = TRUE)    
    pollutantmean <- do.call(rbind , tables)         
}

# Step 2: call the function
x("specdata")

# Step 3: inspect results
head(pollutantmean)

Error in head(pollutantmean) : object 'pollutantmean' not found

Quelle est mon erreur? Quelqu'un peut-il expliquer?

18
Sivanantham C

Il y a beaucoup de code inutile dans votre fonction. Vous pouvez le simplifier pour:

load_data <- function(path) { 
  files <- dir(path, pattern = '\\.csv', full.names = TRUE)
  tables <- lapply(files, read.csv)
  do.call(rbind, tables)
}

pollutantmean <- load_data("specdata")

Soit conscient que do.call + rbind est relativement lent. Vous pourriez trouver dplyr::bind_rows ou data.table::rbindlist pour être sensiblement plus rapide.

47
hadley

Pour mettre à jour la réponse du professeur Wickham ci-dessus avec le code de la bibliothèque la plus récente purrr qu'il a co-écrit avec Lionel Henry:

Tbl <-
    list.files(pattern="*.csv") %>% 
    map_df(~read_csv(.))

Si le transtypage est effronté, vous pouvez forcer toutes les colonnes à être des caractères avec cela.

Tbl <-
    list.files(pattern="*.csv") %>% 
    map_df(~read_csv(., col_types = cols(.default = "c")))

Si vous souhaitez vous plonger dans des sous-répertoires pour construire votre liste de fichiers à lier, assurez-vous d'inclure le nom du chemin et d'enregistrer les fichiers avec leurs noms complets dans votre liste. Cela permettra au travail de liaison de se poursuivre en dehors du répertoire actuel. (En pensant aux chemins d'accès complets comme fonctionnant comme des passeports pour permettre le retour à travers les "frontières" du répertoire.)

Tbl <-
    list.files(path = "./subdirectory/",
               pattern="*.csv", 
               full.names = T) %>% 
    map_df(~read_csv(., col_types = cols(.default = "c"))) 

Comme le décrit le professeur Wickham ici (à mi-chemin environ):

map_df(x, f) est effectivement la même chose que do.call("rbind", lapply(x, f)) mais sous le capot est beaucoup plus efficace.

et un merci à Jake Kaupp pour m'avoir présenté map_df () ici .

7
leerssej

Cela peut être fait de manière très succincte avec du dplyr et du ronronnement du tidyverse. Où x est une liste des noms de vos fichiers csv que vous pouvez simplement utiliser:

bind_rows(map(x, read.csv))

Le mappage de read.csv en x produit une liste de fichiers DFS que bind_rows combine ensuite parfaitement!

3
CClarke
```{r echo = FALSE, warning = FALSE, message = FALSE}

setwd("~/Data/R/BacklogReporting/data/PastDue/global/") ## where file are located

path = "~/Data/R/BacklogReporting/data/PastDue/global/"
out.file <- ""
file.names <- dir(path, pattern = ".csv")
for(i in 1:length(file.names)){
  file <- read.csv(file.names[i], header = TRUE, stringsAsFactors = FALSE)
  out.file <- rbind(out.file, file)
}

write.csv(out.file, file = "~/Data/R/BacklogReporting/data/PastDue/global/global_stacked/past_due_global_stacked.csv", row.names = FALSE) ## directory to write stacked file to

past_due_global_stacked <- read.csv("C:/Users/E550143/Documents/Data/R/BacklogReporting/data/PastDue/global/global_stacked/past_due_global_stacked.csv", stringsAsFactors = FALSE)

files <- list.files(pattern = "\\.csv$") %>%  t() %>% paste(collapse = ", ")
```
1
Dave Headrick

Si vos fichiers csv se trouvent dans un autre répertoire, vous pouvez utiliser quelque chose comme ceci:

readFilesInDirectory <- function(directory, pattern){
  files <- list.files(path = directory,pattern = pattern)
  for (f in files){
    file <- paste(directory,files, sep ="")
    temp <- lapply(file, fread, sep=",")
    data <- rbindlist( temp )
  }
  return(data)
}
0
LBes