【问题标题】:When importing CSV into R how to generate column with name of the CSV?将 CSV 导入 R 时如何生成带有 CSV 名称的列?
【发布时间】:2011-07-08 09:05:15
【问题描述】:

我有大量的 csv 文件要读入 R。csv 中的所有列标题都是相同的。起初我以为我需要根据文件名列表创建一个循环,但搜索后我发现了一种更快的方法。这会正确读取并组合所有 csv(据我所知)。

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 在数据进入 R 时被称为 Chicago_IL.csv,则该行将如下所示:

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

【问题讨论】:

    标签: r


    【解决方案1】:

    发现这个对我有用,它创建新列并合并整个文件夹 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")
    

    这会创建源文件的新列,并将它们合并。

    【讨论】:

      【解决方案2】:

      这是一个使用来自rioimport_list() 函数的解决方案,它就是为此目的而设计的。

      # 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 的维护者。

      【讨论】:

        【解决方案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】:

          您已经完成了所有艰苦的工作。通过相当小的修改,这应该是直截了当的。

          逻辑是:

          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)
          

          请注意,我对您的代码提出了另一个小的改进:read.csv() 返回一个 data.frame - 这意味着您可以使用 ldply() 而不是 llply()。

          【讨论】:

          • 使用 rep 是可选的,ret$Source &lt;- filename 也可以使用
          • @Karsten W,谢谢。我已编辑代码以反映您的建议。
          • 这可能是一个有点傻的问题,但是...当使用您的更改 (ldply()) 时,数据会以所有列标题都转移到行标题和文件名 (带数字)成为列标题。有没有解决的办法?使用 llply 有什么缺点吗?
          • 使用 llply 而不是 ldply 没有固有的缺点。唯一的区别是,如果您希望将数据框作为输出,ldply 会执行此操作,因此您可以节省一步。
          • 我明白了,再次感谢,这个功能的工作方式正是我所希望的。
          【解决方案5】:

          试试这个:

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

          行名将指示源和行号。

          【讨论】:

            【解决方案6】:

            有点凌乱但有效:

            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
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2021-09-14
              • 2015-08-28
              • 2015-03-14
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2013-05-05
              相关资源
              最近更新 更多