【问题标题】:How to merge various csv files having the same two header lines into a single document with one header line only using R?如何仅使用 R 将具有相同两个标题行的各种 csv 文件合并到一个标题行的单个文档中?
【发布时间】:2019-11-24 01:43:29
【问题描述】:

我有各种不同的 CSV 文档,它们都在同一个文件夹中。所有这些文档都有 65 列,标题有相同的两个标题行,它们需要合并到一个文档中。此外,我需要合并标题行。

结构大致如下:

B2.csv:

TP1      TP1            TP2          TP2     TP2
Value    Measurement    Condition    Time    Max_Value
1.09     2.779          1            120     5.885
5.09     2.005          2            180     7.555
9.33     1.889          3            240     1.444
5.00     6.799          4            300     9.125
8.88     3.762          5            360     6.223

B4.csv:

TP1      TP1            TP2          TP2     TP2
Value    Measurement    Condition    Time    Max_Value
2.11     4.339          7            120     6.115
5.69     8.025          8            180     7.555
8.38     5.689          9            240     5.244
9.70     7.795          10           300     8.824
8.78     3.769          11           360     3.883

最终的文档应该如下所示:

TP1_Value    TP1_Measurement    TP2_Condition    TP2_Time    TP2_Max_Value
1.09         2.779               1               120         5.885
5.09         2.005               2               180         7.555
9.33         1.889               3               240         1.444
5.00         6.799               4               300         9.125
8.88         3.762               5               360         6.223
2.11         4.339               7               120         6.115
5.69         8.025               8               180         7.555
8.38         5.689               9               240         5.244
9.70         7.795               10              300         8.824
8.78         3.769               11              360         3.883

为了合并文档,我使用了以下代码:

setwd("C:/Users/XXXX/Desktop/Data/.")

# Get a List of all files in directory named with a key word, say all `.csv` files
filenames <- list.files("C:/Users/XXXX/Desktop/Data/.", pattern="*.csv", full.names=TRUE)

# Read and row bind all data sets
data <- rbindlist(lapply(filenames,fread))

# Generate new CSV document
write.csv(data, file = "C:/Users/XXXX/Desktop/Data/OneHeader.csv", sep = ",", row.names = FALSE)

但是,使用此代码,第二个标题行仍保留在数据文件中。要合并这些标题,我会使用以下代码:

# Merging first two lines into one single header
data[] <- lapply(data, as.character)
names(data) <- paste(names(data), data[1, ], sep = "_")
new_data <- data[-1,]

您能帮我吗,我如何将代码的这两个部分组合成一种自动合并的方式?

如果有人可以帮助我,我将不胜感激,因为我是使用 R 的初学者。或者还有其他(更好的)方法来完成这项任务吗?

非常感谢您的帮助!

【问题讨论】:

    标签: r csv merge lapply rbind


    【解决方案1】:

    这里是一个 data.table 方法,主要使用fread()

    由于它按文件读取列名,因此如果游览文件包含不同的标题,它也可以工作。在rbindlist() 中使用fill = TRUE 填写空白列。

    library( data.table )
    
    #get list of files to read
    files <- list.files( pattern = "^B[0-9].csv", full.names = TRUE )
    
    #read files to list using lapply
    l <- lapply( files, function(x) {
      #read the first two rows of each file, and paste them together to get col_names
      col_names = transpose( fread( x, nrows = 2 ) )[, .(paste(V1, V2, sep = "_") )][[1]]
      #read file from except the first two rows, use col_names as header
      dt <- fread( x, skip = 2, col.names = col_names )
      })
    
    #bind list together
    rbindlist( l, fill = TRUE )
    
    #    TP1_Value TP1_Measurement TP2_Condition TP2_Time TP2_Max_Value
    # 1:      1.09           2.779             1      120         5.885
    # 2:      5.09           2.005             2      180         7.555
    # 3:      9.33           1.889             3      240         1.444
    # 4:      5.00           6.799             4      300         9.125
    # 5:      8.88           3.762             5      360         6.223
    # 6:      2.11           4.339             7      120         6.115
    # 7:      5.69           8.025             8      180         7.555
    # 8:      8.38           5.689             9      240         5.244
    # 9:      9.70           7.795            10      300         8.824
    # 10:     8.78           3.769            11      360         3.883
    

    然后将结果写入磁盘。

    【讨论】:

      【解决方案2】:

      这是一个基本的 R 解决方案。

      首先,获取文件名。正则表达式模式假定它们都以大写 "B" 开头,后跟 1 个或多个数字,并且文件扩展名是 ".csv"

      fnames <- list.files(pattern = "^B\\d+\\.csv")
      

      其次,使用lapply 循环将它们全部读入,跳过第一行。然后,rbind 将几个数据帧放在一起。

      df_list <- lapply(fnames, read.table, skip = 2, sep = ",")
      df_final <- do.call(rbind, df_list)
      

      现在是列名。
      readLines 读取文本行,strsplit 将它们分成列名的组成部分。

      header <- readLines(fnames[1], n = 2)
      header <- strsplit(header, ",")
      names(df_final) <- paste(header[[1]], header[[2]], sep = "_")
      

      查看结果。

      df_final
      #   TP1_Value TP1_Measurement TP2_Condition TP2_Time TP2_Max_Value
      #1       1.09           2.779             1      120         5.885
      #2       5.09           2.005             2      180         7.555
      #3       9.33           1.889             3      240         1.444
      #4       5.00           6.799             4      300         9.125
      #5       8.88           3.762             5      360         6.223
      #6       2.11           4.339             7      120         6.115
      #7       5.69           8.025             8      180         7.555
      #8       8.38           5.689             9      240         5.244
      #9       9.70           7.795            10      300         8.824
      #10      8.78           3.769            11      360         3.883
      

      【讨论】:

        【解决方案3】:

        由于您总是从我收集的内容中获得相同的标题,因此我只需使用正则表达式从插入的数据对象中删除这些第二个标题行,如下所示:

        data <- data[!grepl(*.Value.*, data$TP1),] # removes all the lines that have the term Value on data$TP1 column
        

        然后你可以随意重命名你的第一个标题:

        colnames(data) <- c('TP1_Value', ....)
        

        【讨论】:

          【解决方案4】:

          试试这个:

          filenames <- list.files("C:/Users/XXXX/Desktop/Data/.", pattern="*.csv", full.names=TRUE)
          data <- lapply(filenames, read.csv, skip = 2)
          dataDF <- as.data.frame(do.call("rbind", data), stringsAsFactors = FALSE)
          headersDF<- read.csv(filenames[[1]], nrows= 2, header = FALSE, stringsAsFactors = FALSE)
          names(dataDF) <- paste(headersDF[1,], headersDF[2,], sep = "_")
          write.csv(data, file = "C:/Users/XXXX/Desktop/Data/OneHeader.csv", sep = ",", row.names = FALSE)
          

          基本上你会做以下事情:

          第 1 行使用您提供的目录中的 csv 文件的名称创建一个向量。

          第 2 行将所有文件中的数据读取到数据帧列表中。它会跳过每个文件的前两行。

          第 3 行将矩阵中的不同数据帧绑定为一个。 (现在你有了你的文件,你缺少的是列名)

          第 4 行将第一个文件(您的标题)中的前两行读取到 data.frame 中。

          第 5 行使用“_”作为分隔符逐元素粘贴两行,并将此字符串设置为列名。

          第 6 行写入您的 csv。

          【讨论】:

          • 我会评论代码,但我不在电脑上,无法更改语言。
          • 我已经尝试过了,但是当我执行它时,它会在第三行产生以下错误: data.frame(..., check.names = FALSE) 中的错误:Argumente implizieren unterschiedliche Anzahl Zeilen:31139、42009、50686、47652、51729、53579。我该如何解决?
          • 再试一次。代码的第一个版本中存在错误。在第 3 行它是 as.data.frame(do.call("cbind", data), stringsAsFactors = FALSE) 不是 as.data.frame(do.call("rbind", data), stringsAsFactors = FALSE)。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-06-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-04-15
          相关资源
          最近更新 更多