我有一个充满csv文件的目录,这些文件都有一个公共列(Class
),然后是一个整数值,尽管它们的文件大小不一致。一个例子[1:5, ]
:
Class Abundance_inds
1 Chaetognath 2
2 Copepod_Calanoid_Acartia_spp 9
3 Copepod_Calanoid_Centropages_spp 4
4 Copepod_Calanoid_Temora_spp 1
5 Copepod_Calanoid_Unknown 5
它们正在导出另一个 R 脚本,因此在合并之前需要裁剪第一列,我可以使用以下方法成功合并它们:
test <- read.csv(file = csvs[1])[ ,2:3]
test2 <- read.csv(file = csvs[2])[ ,2:3]
然后:
library(tidyverse)
mergedcsvs <- list(test, test2) %>% reduce(full_join, by = "Class")
无论[1:4,]
多少文件,都会给出以下和期望的结果:
Class Abundance_inds.x Abundance_inds.y
1 Chaetognath 2 4
2 Copepod_Calanoid_Acartia_spp 9 11
3 Copepod_Calanoid_Centropages_spp 4 8
4 Copepod_Calanoid_Temora_spp 1 NA
我还想使用文件的basename
作为列标题,我知道我可以提取的是使用它:
basename1 <- csvs[1]
basename2 <- csvs[2]
我知道我可以创建一个basenames
列表,然后使用这些列标题,但是为每个csv(有很多)创建一个数据帧然后手动执行此操作似乎很不切实际。
当 CSV 从另一个 R 脚本导出时,它们具有另一个不需要的第一列,需要删除该列。
当然有更好的方法!任何帮助都会很棒。
(我对此一团糟,但我无法让它为我工作)
非常感谢
使用最后注释中显示的测试输入读取filenames
字符向量中给出的文件,然后merge
它们。 最后设置名称。 工具包附带,因此您无需安装它。
library(tools)
LL <- Map(read.csv, filenames, as.is = TRUE)
r <- Reduce(function(...) merge(..., all = TRUE, by = "Class"), LL)
names(r)[-1] <- basename(file_path_sans_ext(filenames))
给:
Class DF1 DF2 DF3
1 Chaetognath 2 NA 2
2 Copepod_Calanoid_Acartia_spp 9 9 9
3 Copepod_Calanoid_Centropages_spp 4 4 NA
4 Copepod_Calanoid_Temora_spp 1 1 1
5 Copepod_Calanoid_Unknown NA 5 5
根据您想要的输出内容,您可能需要all = FALSE
来代替显示的all
参数。
注意
这次我在下面为您提供了测试数据,但这确实应该在问题中提供,以及您期望的输出。
Lines <- " Class Abundance_inds
1 Chaetognath 2
2 Copepod_Calanoid_Acartia_spp 9
3 Copepod_Calanoid_Centropages_spp 4
4 Copepod_Calanoid_Temora_spp 1
5 Copepod_Calanoid_Unknown 5"
DF <- read.table(text = Lines, as.is = TRUE)
L <- list(DF1 = DF[1:4, ], DF2 = DF[2:5, ], DF3 = DF[-3, ])
filenames <- paste0(names(L), ".csv")
for(i in seq_along(filenames)) write.csv(L[[i]], filenames[i], row.names = FALSE)
使用快速fread
的又一个答案library(data.table)
library(tidyverse)
library(data.table)
library(tools)
write.csv(data.frame(stringsAsFactors=FALSE,
Class = c("Chaetognath", "Copepod_Calanoid_Acartia_spp",
"Copepod_Calanoid_Centropages_spp",
"Copepod_Calanoid_Temora_spp"),
Abundance_inds = c(2, 9, 4, 1)
), file = "x.csv")
write.csv(data.frame(stringsAsFactors=FALSE,
Class = c("Chaetognath", "Copepod_Calanoid_Acartia_spp",
"Copepod_Calanoid_Centropages_spp"),
Whatever = c(4, 11, 8)
), file = "y.csv")
csvPaths <- list.files(".", "\.csv$", full.names = TRUE)
csvList <- list()
for(csvPath in csvPaths){
csvList[[csvPath]] <- fread(csvPath, col.names = c("Class", basename(file_path_sans_ext(csvPath))), drop = 1)
}
mergedcsvs <- csvList %>% reduce(full_join, by = "Class")
# Class x.csv y.csv
# 1 Chaetognath 2 4
# 2 Copepod_Calanoid_Acartia_spp 9 11
# 3 Copepod_Calanoid_Centropages_spp 4 8
# 4 Copepod_Calanoid_Temora_spp 1 NA
编辑:这是一个data.table
唯一的方法(避免library(tidyverse)
)
csvPaths <- list.files(".", "\.csv$", full.names = TRUE)
csvList <- list()
for(csvPath in csvPaths){
csvList[[csvPath]] <- fread(csvPath, drop = 1, col.names = c("class", "vars"))[, id := basename(file_path_sans_ext(csvPath))]
}
DT <- rbindlist(csvList, use.names = FALSE)
mergedDT <- dcast.data.table(DT, class ~ id, value.var = "vars")
mergedDT
一种可能性是将data.frames读入嵌套的tibble中。 因此,首先定义一个描述如何读取和转换单个数据帧的函数。在您的情况下,它看起来像这样:
library(tidyverse)
read_onecsv <- function(csvname, columnname) {
read.csv(file = csvname) %>% as_tibble() %>%
select(2:3) %>% mutate(type = columnname)
}
此函数读取一个 csv 文件,将其转换为 tibble,选择列 2 和 3,然后创建一个包含后面列名称的虚拟列(名为type
)。
接下来,创建一个包含所有csvnames
和所有columnnames
的 tibble,并运行以下命令:
tibble(csvnames = c("csv1.csv", "csv2.csv"), columnnames = c("col1", "col2")) %>%
mutate(data = map2(csvnames, columnnames, read_onecsv))%>%
unnest() %>%
spread(type, Abundance_inds)
具有list.files
和lapply
的可能解决方案。
library(readr)
## read all names with .csv at the end form your working directory and save as variable
fileNames <- list.files(pattern = '.csv')
## read all files, merge and save as tibble
fileList <- lapply(1:length(fileNames), function(i) read_csv(fileNames[i]) %>%
select(-1)
) %>%
reduce(full_join, by = 'class')
## rename columns
names(fileList) <- c(names(fileList)[1], sub('.csv', "", fileNames))
## output
# A tibble: 4 x 3
class test1 test10
<chr> <dbl> <dbl>
1 banana 1 1
2 apples 1 1
3 orange 10 NA
4 ginger NA 5
我创建了两个.csv文件(test1.csv和test10.csv)用于测试目的
文件测试1.csv
number, class,value
1,banana,1
2,apples,1
3,orange,10
文件测试10.csv
number, class,value
1,banana,1
2,apples,1
3,ginger,5