KANG1943
我在一个自定义函数(下文称为函数1)中用
ggplot()
画图,然后在另外一个自定义函数(下文称为函数2)中引用了函数1,但是在执行函数2的时候,不希望生成的图片被打印出来。详情如下。
# 载入需要的包
library(ggplot2)
library(ggpubr)
# 构建数据
mydata <- data.frame(name_1 = c(1: 10),
name_2 = c(11: 20),
name_3 = c(111: 120))
# 函数1:以下函数能对数据的某一列作图
func_plot <- function(var_data, name) {
# 作图参数设置
plot_data <- ggplot() +
geom_point(aes(c(1:10), mydata[, name])) +
labs(y = name)
# 把图打出来
print(plot_data)
func_plot(mydata, "name_1")
# 可以看到输出了一个图如下
# 函数2:以下函数能对数据的所有列作图
func_plot_df <- function(var_data) {
# 建一个列表先存储要打印的图
plot_ls <- vector("list")
for (i in names(var_data)) {
plot_ls[[i]] <- func_plot(var_data, i)
# 然后把这些图安排在一个2 X 2的画布上
ggarrange(plotlist = plot_ls, nrow = 2, ncol = 2)
func_plot_df(mydata)
可以看到输出四个图如下
想达到的效果是:
执行函数1的时候,能正常打印图片;而执行函数2的时候,只输出第四个图,而不输出前三个。
可能的解决方法:
目前函数2是基于函数1建立的,如果将函数1的源代码整合到函数2的源代码中并稍加修改,就可以实现我想要的效果。但是这样维护起来就比较麻烦,比如我想对函数1和函数2打印出图的样式做改变的话,就需要对两段源代码都做修改。
拓展:
这段描述跟问题本身没有关系,主要解释我为什么希望解决这个问题,可以忽略。通过这个提问想解决的问题其实是,我需要两个函数,一个是对数据框的特定列作图,而另一个是对每一列作图,并将他们排在一个2x2的画布上以便查看。后者相当于对前者功能的一个扩展:前者应用于简单向量,后者应用于数据框。甚至,我还需要在这个基础上写一个列表版本的函数,实现类似的功能,只不过打印出图的排列形式也要进行一定的精简,以便查看。
KANG1943
barnett874
哈哈哈,意外的回答。不好意思,我没说清楚哈。我是希望第一函数能打印出来图片,而第二个函数只打出第四个图片。想了一下,增加了一个输入变量,目前的解决方案是:
# 载入需要的包
library(ggplot2)
library(ggpubr)
# 构建数据
mydata <- data.frame(name_1 = c(1: 10),
name_2 = c(11: 20),
name_3 = c(111: 120))
# 函数1:以下函数能对数据的某一列作图
func_plot <- function(var_data, name, figure = TRUE) {
# 作图参数设置
plot_data <- ggplot() +
geom_point(aes(c(1:10), mydata[, name])) +
labs(y = name)
# 把图打出来
if (figure == TRUE) {print(plot_data)} else {plot_data}
# 运行函数1,出一个大图
func_plot(mydata, "name_1")
# 函数2:以下函数能对数据的所有列作图
func_plot_df <- function(var_data) {
# 建一个列表先存储要打印的图
plot_ls <- vector("list")
for (i in names(var_data)) {
plot_ls[[i]] <- func_plot(var_data, i, figure = FALSE)
# 然后把这些图安排在一个2 X 2的画布上
ggarrange(plotlist = plot_ls, nrow = 2, ncol = 2)
# 运行函数2,几个分开的大图不打印,只打印最后拼出来的图
func_plot_df(mydata)
plot_ls <- vector("list")
for (i in names(var_data)) {
plot_ls[[i]] <- invisible(func_plot(var_data, i)) #使用invisible
# 然后把这些图安排在一个2 X 2的画布上
ggarrange(plotlist = plot_ls, nrow = 2, ncol = 2)
func_plot_df(mydata)
yihui
我不明白你们绕这么大一圈在干啥,直接把最初的代码中的
print()
去掉就可以了啊。下面的
invisible()
函数并不起任何作用,它只在顶层表达式中才有用:
https://yihui.org/en/2017/06/top-level-r-expressions/
用在
for
循环内的话,那就不是顶层表达式。一个表达式内部的值是不会被打印出来的,只有顶层表达式的最后一个值会打印。所以
for
循环内的这个
invisible()
有或没有都没关系,问题不是出在这里,而是最初第一个函数显式调用了
print()
,通常来说这不是编程的好习惯。除非不可避免,否则函数尽量只返回值,而不要涉及副作用(打印就是常见的副作用)。