Подтвердить что ты не робот

При импорте CSV в R как создать столбец с именем CSV?

У меня есть большое количество файлов csv, которые я хочу прочитать в R. Все заголовки столбцов в csvs одинаковы. Сначала мне показалось, что мне нужно создать цикл, основанный на списке имен файлов, но после поиска я нашел более быстрый способ. Это читает и объединяет все csvs правильно (насколько я знаю).

filenames <- list.files(path = ".", pattern = NULL, all.files = FALSE, full.names = FALSE, recursive = FALSE, ignore.case = FALSE)

library(plyr)
import.list <- llply(filenames, read.csv)

combined <- do.call("rbind", import.list)

Единственная проблема заключается в том, что я хочу знать, из какой csv возникает определенная строка данных. Мне нужен столбец с меткой "источник", который содержит имя csv, из которого была получена определенная строка. так, например, если csv был вызван Chicago_IL.csv, когда данные попали в R, строка выглядела бы примерно так:

> City    State   Market  etc Source  
> Burbank IL      Western etc Chicago_IL
4b9b3361

Ответ 1

Вы уже проделали всю тяжелую работу. При довольно небольшой модификации это должно быть прямолинейным.

Логика такова:

  • Создайте небольшую вспомогательную функцию, которая читает отдельный csv и добавляет столбец с именем файла.
  • Вызов этой вспомогательной функции в llply()

Следующее должно работать:

read_csv_filename <- function(filename){
    ret <- read.csv(filename)
    ret$Source <- filename #EDIT
    ret
}

import.list <- ldply(filenames, read_csv_filename)

Обратите внимание, что я предложил другое небольшое улучшение для вашего кода: read.csv() возвращает data.frame - это означает, что вы можете использовать ldply(), а не llply().

Ответ 2

Попробуйте следующее:

do.call("rbind", sapply(filenames, read.csv, simplify = FALSE))

Имена строк будут указывать номер источника и номера.

Ответ 3

data.table решение

Обновление: вот полное решение для data.table для этого, используя keep.rownames. Предполагая, что все ваши CSV находятся в одной папке:

library(data.table)
my.path <- "C:/some/path/to/your/folder" #set the path
filenames <- paste(my.path, list.files(path=my.path), sep="/") #list of files

#this will create a rn column with the path in it
my.dt<- data.table(do.call("rbind", sapply(filenames, read.csv,     
                  sep=";")), keep.rownames = T)

Базовое синтаксическое решение

Я использовал решение Grothendieck и добавил строку для создания столбца из имен строк. Проще всего:

something <- do.call("rbind", sapply(filenames, read.csv, sep=";", simplify = FALSE)) 
something$mycolumn <- row.names(something)

Если вам нужна только часть имени файла, замените вторую строку следующим образом:

something$mycolumn <- substring(row.names(something),1,3)

Это будет использовать первые 3 символа из имени файла в качестве значения в новом столбце.

Ответ 4

Вот решение, использующее функцию import_list() из rio, которая предназначена именно для этой цели,

# setup some example files to import
rio::export(mtcars, "mtcars1.csv")
rio::export(mtcars, "mtcars2.csv")
rio::export(mtcars, "mtcars3.csv")

Поведение import_list() по умолчанию - это получить список фреймов данных:

str(rio::import_list(dir(pattern = "mtcars")), 1)
## List of 3
##  $ :'data.frame':       32 obs. of  11 variables:
##  $ :'data.frame':       32 obs. of  11 variables:
##  $ :'data.frame':       32 obs. of  11 variables:

Но вы можете использовать аргумент rbind, чтобы вместо этого создать единый фрейм данных (обратите внимание на столбец _file в конце):

str(rio::import_list(dir(pattern = "mtcars"), rbind = TRUE))
## 'data.frame':   96 obs. of  12 variables:
##  $ mpg  : num  21 21 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 ...
##  $ cyl  : int  6 6 4 6 8 6 8 4 4 6 ...
##  $ disp : num  160 160 108 258 360 ...
##  $ hp   : int  110 110 93 110 175 105 245 62 95 123 ...
##  $ drat : num  3.9 3.9 3.85 3.08 3.15 2.76 3.21 3.69 3.92 3.92 ...
##  $ wt   : num  2.62 2.88 2.32 3.21 3.44 ...
##  $ qsec : num  16.5 17 18.6 19.4 17 ...
##  $ vs   : int  0 0 1 1 0 1 0 1 1 1 ...
##  $ am   : int  1 1 1 0 0 0 0 0 0 0 ...
##  $ gear : int  4 4 4 3 3 3 3 4 4 4 ...
##  $ carb : int  4 4 1 1 2 1 4 2 2 4 ...
##  $ _file: chr  "mtcars1.csv" "mtcars1.csv" "mtcars1.csv" "mtcars1.csv" ...

и аргумент rbind_label, чтобы указать имя столбца, который идентифицирует каждый файл:

str(rio::import_list(dir(pattern = "mtcars"), rbind = TRUE, rbind_label = "source"))
## 'data.frame':   96 obs. of  12 variables:
##  $ mpg   : num  21 21 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 ...
##  $ cyl   : int  6 6 4 6 8 6 8 4 4 6 ...
##  $ disp  : num  160 160 108 258 360 ...
##  $ hp    : int  110 110 93 110 175 105 245 62 95 123 ...
##  $ drat  : num  3.9 3.9 3.85 3.08 3.15 2.76 3.21 3.69 3.92 3.92 ...
##  $ wt    : num  2.62 2.88 2.32 3.21 3.44 ...
##  $ qsec  : num  16.5 17 18.6 19.4 17 ...
##  $ vs    : int  0 0 1 1 0 1 0 1 1 1 ...
##  $ am    : int  1 1 1 0 0 0 0 0 0 0 ...
##  $ gear  : int  4 4 4 3 3 3 3 4 4 4 ...
##  $ carb  : int  4 4 1 1 2 1 4 2 2 4 ...
##  $ source: chr  "mtcars1.csv" "mtcars1.csv" "mtcars1.csv" "mtcars1.csv" ...

Для полного раскрытия: я являюсь хранителем rio.

Ответ 5

Своеобразное, но работает:

filenames <- c("foo.csv","bar.csv")
import.list <- list(matrix(,4,4),matrix(6,6))

source <- unlist(sapply(1:length(filenames),function(i)rep(gsub(".csv","",filenames[i]),nrow(import.list[[i]]))))

source
[1] "foo" "foo" "foo" "foo" "bar" "bar" "bar" "bar" "bar" "bar"

combined$source <- source

Ответ 6

Нашел этот, который работает для меня, который создает новый столбец плюс слияние целых файлов csv.

Использование setNames():

file.list <- list.files(pattern = '*.csv')
file.list <- setNames(file.list, file.list)

df.list <- lapply(file.list, read_csv)
df.list <- Map(function(df, name) {
  df$issue <- name
  df
}, df.list, names(df.list))
df <- rbindlist(df.list,use.names = TRUE, fill = TRUE, idcol = "Issue")

Это создает новый столбец исходного файла и объединяет их.

Ответ 7

Здесь решение, которое использует как data.table, так и plyr:

library(plyr) 
library(data.table)
my.path <- "C:/something/"

filenames <- paste(my.path, list.files(path=my.path), sep="/")
DT <- data.table(do.call("rbind", sapply(filenames, read.csv, sep=";",
                       simplify = FALSE, stringsAsFactors=FALSE)),keep.rownames = T)

Keep.rownames = T создаст столбец с именем rn. Если вы хотите, чтобы только имя файла (без пути или расширения) делалось примерно так:

DT[, cool.names := as.factor(substring(basename(rn),1,3))]