При импорте CSV в R, как создать столбец с именем CSV? - PullRequest
20 голосов
/ 04 марта 2011

У меня есть большое количество 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

Ответы [ 6 ]

23 голосов
/ 04 марта 2011

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

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

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

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

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

import.list <- ldply(filenames, read_csv_filename)

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

13 голосов
/ 04 марта 2011

Попробуйте:

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

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

4 голосов
/ 29 сентября 2016

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)

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

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

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

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

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

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

3 голосов
/ 08 августа 2017

Вот решение с использованием функции 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" ...

Для полного раскрытия: я поддерживаю Рио.

1 голос
/ 04 марта 2011

Вроде грязно, но работает:

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
0 голосов
/ 23 апреля 2018

Нашел этот работающий для меня, который создает новый столбец плюс слияние целых папок 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")

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...