如何仅使用R将具有相同两个标题行的各种csv文件合并到一个标题行的单个文档中?

时间:2019-07-15 10:58:21

标签: r csv merge lapply rbind

我在同一文件夹中有各种不同的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的初学者。或者还有其他(更好的)方法可以完成此任务吗?

非常感谢您的帮助!

4 个答案:

答案 0 :(得分:2)

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

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

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

然后将结果写入磁盘。

答案 1 :(得分:1)

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

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

然后,您可以使用以下方法随意重命名第一个标头:

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

答案 2 :(得分:1)

尝试一下:

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。

答案 3 :(得分:1)

这是基本的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