При импорте 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
Ответы
Ответ 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))]