web-dev-qa-db-ja.com

rbindを使用してRの複数の.csvファイルを単一のデータフレームにロードする私の機能の何が問題になっていますか?

300個の.csvファイルを結合する次の関数を記述しました。私のディレクトリ名は「specdata」です。実行のために次の手順を実行しました、

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

私の間違いは何ですか?誰か説明していただけますか?

18
Sivanantham C

関数には不要なコードがたくさんあります。次のように簡略化できます。

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

do.call + rbindは比較的遅いことに注意してください。 dplyr::bind_rowsまたはdata.table::rbindlistの方が大幅に高速である場合があります。

47
hadley

上記のWickham教授の回答を最新の purrr library のコードで更新するには、Lionel Henryと共同執筆しました。

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

型キャストが生意気な場合は、これを使用してすべての列を文字にすることができます。

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

サブディレクトリにディップして、最終的にバインドするファイルのリストを作成する場合は、パス名を含め、ファイルを完全な名前でリストに登録してください。これにより、バインド作業を現在のディレクトリの外で行うことができます。 (完全なパス名をパスポートのように動作して、ディレクトリ「境界」を越えて戻ることができると考えてください。)

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

ウィッカム教授が here について説明しているように(約半分):

map_df(x, f)do.call("rbind", lapply(x, f))と実質的に同じですが、内部でははるかに効率的です。

そして、map_df() here を紹介してくれたJake Kauppに感謝します。

7
leerssej

これは、tidyverseのdplyrおよびpurrrを使用して非常に簡潔に行うことができます。 xは、単純に使用できるcsvファイルの名前のリストです。

bind_rows(map(x, read.csv))

Read.csvをxにマッピングすると、bind_rowsがきちんと結合するdfのリストが生成されます。

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

Csvファイルが別のディレクトリにある場合は、次のようなものを使用できます。

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