【问题标题】:Convert R plotting commands into loop for many files将 R 绘图命令转换为许多文件的循环
【发布时间】:2019-10-07 15:42:44
【问题描述】:

目前我一直在使用 R 读取表格并绘制一些我保存为 png 文件的数据。现在我有 100 个文件,希望这个过程能够自动化,而不是手动更改路径 100 次。

此外,我想将 100 个文件加入 R 中的一个表中,以便随后进行分析。连接将采用 dplyr 的 bind_rows 格式,因为所有文件都具有相同的列标题。当我在 R 中有两个表时,我已经这样做了,但现在当我使用循环按顺序读取文件时。在 R 中执行此操作的最佳方法是什么?提前感谢您的任何建议或帮助。

my_data <- read.table('/path/to/data/results/sample_1.txt', header = TRUE, sep = "\t")

ggplot(my data, aes(x=alt_freq)) + geom_histogram(color="black", fill="white", bins = 20) + xlim(c(0,1))

ggsave("/path/to/plots/sample_1.png", plot = last_plot(),width = 16, height = 9)

#append table to one large table in the format of dplyr::bind_rows(y, z)

输入文件都以相同的命名约定命名:

sample_1.txt
sample_2.txt
sample_3.txt

文件看起来像:

sample_name position    alt_freq    ref_freq    sample_1_counts
sample 1    10  0.5 0.5 2
sample 1    20  0.25    0.75    4

所有的txt文件都在同一个目录下,所有的txt文件都是感兴趣的。

【问题讨论】:

  • 所有文件都在同一个目录下吗?是否所有感兴趣的目录中的.txt 文件?
  • 是的,没错

标签: r loops ggplot2 plot dplyr


【解决方案1】:

首先收集感兴趣的文件的完整路径

library(ggplot2)
all_files <- list.files("/path/to/data/results", pattern = "sample_\\d+\\.txt$", 
             full.names = TRUE)

然后创建一个函数应用到每个文件

new_fun <- function(path_of_file) {
  my_data <- read.table(path_of_file, header = TRUE)

  ggplot(my_data, aes(x=alt_freq)) + 
   geom_histogram(color="black", fill="white", bins = 20) + xlim(c(0,1))

  ggsave(paste0(dirname(path_of_file), "/", sub("txt$", "png", 
  basename(path_of_file))), plot = last_plot(),width = 16, height = 9)
}

我们使用paste0 来创建路径以通过获取目录名称并将结尾的txt 替换为png 来动态保存绘图。

然后使用lapply/map/for循环将new_fun应用于每个文件

lapply(all_files, new_fun)

我们可以将所有文件合并到一个数据帧中

combined_data <- do.call(rbind, lapply(all_files, read.table, header = TRUE))

如果某一列的标题不同,我们可以更改该特定列的列名,然后更改rbind。所以例如,如果第 1 列的标题信息不同,我们可以这样做

combined_data  <- do.call(rbind, lapply(all_files, function(x) {
   df <- read.table(x, header = TRUE)
   names(df)[1] <- "new_header"
   df$filename <- basename(x)
   df
}))

【讨论】:

  • 这很好用,除了我发现每个文件中的列名之一包含示例名称。所以 rbind 失败了,因为不是所有的列名都匹配。但是,跨文件的列顺序是相同的。有没有办法合并文件,忽略列名的这种变化,只保留第一个文件的标题?或者完全忽略标题,然后我会添加一个标题?
  • @user964689 我已经更新了答案的最后一部分,您可以根据您的实际数据更改列号(我在这里使用了1)。它现在应该可以工作了。
  • 非常感谢。这可能应该是一个新问题,但如果您不介意,是否有办法将文件名添加为列,这样当我合并所有文件时,我可以看到哪些行属于哪个样本?通常我会使用 dplyr 的 mutate 来创建一个新列,其中示例名称为字符串,但在合并每个文件时自动执行此操作会很棒。感谢您的帮助。
  • @user964689 是的,更新了答案。添加了一个名为 filename 的新列,其中包含文件名。
【解决方案2】:

我会做如下的事情。

将这些更改为它们的真实值。

in_dir <- '/path/to/data/results'
out_dir <- '/path/to/plots'

现在是绘图和绑定表格。

library(ggplot2)

old_dir <- getwd()
setwd(in_dir)

flnames <- list.files(pattern = '^sample_[[:digit:]]+\\.txt$')
data_list <- lapply(flnames, read.table, header = TRUE, sep = '\t')

lapply(seq_along(data_list), function(i){
  ggplot(data_list[[i]], aes(x = alt_freq)) + 
    geom_histogram(color = "black", fill = "white", bins = 20) + 
    xlim(c(0, 1))
  f <- sub('txt$', 'png', flname[i])
  outfile <- paste(out_dir, f, sep = '/')
  ggsave(outfile, plot = last_plot(),width = 16, height = 9)
})

data_all <- dplyr::bind_rows(data_list)

最后的清理。

setwd(old_dir)

## NOT RUN
#rm(data_list)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-06-01
    • 1970-01-01
    • 2016-10-18
    • 2020-11-02
    • 1970-01-01
    • 2020-11-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多