如何仅使用 R 将具有相同的两个 header 行的各种 csv 文件合并到一个具有一个 header 行的单个文档中?
How to merge various csv files having the same two header lines into a single document with one header line only using R?
我有各种不同的 CSV 文档,它们都在同一个文件夹中。所有这些文档都有 65 列,标题为相同的两行 header,它们需要合并到一个文档中。此外,我需要合并 header 行。
结构大致如下所示:
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 的初学者。或者是否有其他(更好的)方法来完成此任务?
非常感谢您的帮助!
因为你总是从我收集的数据中得到相同的 headers,我只是使用正则表达式从我插入的数据 object 中删除这些第二行 header 像这样:
data <- data[!grepl(*.Value.*, data$TP1),] # removes all the lines that have the term Value on data$TP1 column
然后您可以随意重命名您的第一个 header:
colnames(data) <- c('TP1_Value', ....)
试试这个:
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 行将第一个文件(您的 header)的前两行读入 data.frame。
第 5 行使用“_”作为分隔符按元素粘贴两行,并将此字符串设置为列名。
第 6 行写入您的 csv。
这是一个 data.table 方法,主要使用 fread()
。
由于它按文件读取列名称,因此如果游览文件包含不同的 headers,它也可以工作。在rbindlist()
中使用fill = TRUE
填写blank-columns.
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
然后将结果写入磁盘。
这是基本的 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
我有各种不同的 CSV 文档,它们都在同一个文件夹中。所有这些文档都有 65 列,标题为相同的两行 header,它们需要合并到一个文档中。此外,我需要合并 header 行。
结构大致如下所示:
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 的初学者。或者是否有其他(更好的)方法来完成此任务?
非常感谢您的帮助!
因为你总是从我收集的数据中得到相同的 headers,我只是使用正则表达式从我插入的数据 object 中删除这些第二行 header 像这样:
data <- data[!grepl(*.Value.*, data$TP1),] # removes all the lines that have the term Value on data$TP1 column
然后您可以随意重命名您的第一个 header:
colnames(data) <- c('TP1_Value', ....)
试试这个:
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 行将第一个文件(您的 header)的前两行读入 data.frame。
第 5 行使用“_”作为分隔符按元素粘贴两行,并将此字符串设置为列名。
第 6 行写入您的 csv。
这是一个 data.table 方法,主要使用 fread()
。
由于它按文件读取列名称,因此如果游览文件包含不同的 headers,它也可以工作。在rbindlist()
中使用fill = TRUE
填写blank-columns.
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
然后将结果写入磁盘。
这是基本的 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