If else 条件在 ggplot 中添加额外的图层

假设我想在 ggplot 中绘制两个层,一个包含点,另一个包含线,如果满足某个条件的话。

没有标准的代码可能是这样的:

library("ggplot2")


# Summarise number of movie ratings by year of movie
mry <- do.call(rbind, by(movies, round(movies$rating), function(df) {
nums <- tapply(df$length, df$year, length)
data.frame(rating=round(df$rating[1]), year = as.numeric(names(nums)), number=as.vector(nums))
}))


p <- ggplot(mry, aes(x=year, y=number, group=rating))


p +
geom_point()+
geom_line()

现在,绘制点(而不仅仅是线)的条件是,名为 tmp.data 的对象不等于表达式“ no value”。

tmp.data<-c(1,2,3) # in this case the condition is fulfilled


# attempt to plot the two layers including the condition in the plotting function
p+
if(tmp.data[1]!="no value"){ geom_point()+}
geom_line()

失败了。

Error: unexpected '}' in:
"p+
if(tmp.data[1]!="no value"){ geom_point()+}"

Geom _ line () 返回文章页面
Stat _ Identity:
Position _ Identity: (width = NULL,height = NULL)

55223 次浏览

What you are seeing is a syntax error. The most robust way I can think of is:

tmp.data<-c(1,2,3)
if(tmp.data[1]!="no value") {
p = p + geom_point()
}
p + geom_line()

So you compose the object p in a sequence, only adding geom_point() when the if statements yields TRUE.

library(ggplot2)


# Summarise number of movie ratings by year of movie
mry <- do.call(rbind, by(movies, round(movies$rating), function(df) {
nums <- tapply(df$length, df$year, length)
data.frame(rating=round(df$rating[1]), year = as.numeric(names(nums)), number=as.vector(nums))
}))


tmp.data<-c(1,2,3) # in this case the condition is fulfilled


p <- ggplot(mry, aes(x=year, y=number, group=rating))


# this won't "loop through" the data points but it's what you asked for
if (tmp.data[1]!="no value") {
p <- p + geom_point() + geom_line()
} else {
p <- p + geom_line()
}
p

g1

but perhaps this is more like what you really want?

mry$rating <- factor(mry$rating)
p <- ggplot(mry, aes(x=year, y=number, group=rating))
p <- p + geom_line()
p <- p + geom_point(data=mry[!(mry$rating %in% tmp.data),],
aes(x=year, y=number, group=rating, color=rating), size=2)
p <- p + scale_color_brewer()
p

g2

This was done using ggplot2 2.1.0. I think you can do exactly what the OP wished, just by switching the parenthesis so that they encompass the entire if statement.

Here is an example that add a horizontal line depending on if Swtich is T or F. First, where the condition is TRUE

library(ggplot2)


df<-data.frame(x=1:10,y=11:20)
Switch=T


ggplot(df,aes(x,y))+
{if(Switch)geom_hline(yintercept=15)}+
geom_point()

enter image description here

Now, the same thing but the condition is FALSE

df<-data.frame(x=1:10,y=11:20)
Switch=F


ggplot(df,aes(x,y))+
{if(Switch)geom_hline(yintercept=15)}+
geom_point()

enter image description here

Following the ggplot2 book, you can create a function which returns a list. Any NULL components will be ignored.

library(ggplot2)
library(ggplot2movies)


# Summarise number of movie ratings by year of movie
mry <- do.call(rbind, by(movies, round(movies$rating), function(df) {
nums <- tapply(df$length, df$year, length)
data.frame(rating=round(df$rating[1]), year = as.numeric(names(nums)), number=as.vector(nums))
}))


# create function to add points conditionally
# If the list contains any NULL elements, they’re ignored.
my_plot <- function(point = FALSE){
list(
geom_line(),
if (point)
geom_point()
)


}


p <- ggplot(mry, aes(x=year, y=number, group=rating))
p + my_plot()

p + my_plot(point = TRUE)

Created on 2020-02-25 by the reprex package (v0.3.0)

An alternative example using iris dataset creating a plot with conditional components, some with more than one line, and with multiple switches.

library("ggplot2")


p <- ggplot(iris,
aes(x=Sepal.Length,
y=Sepal.Width,
colour=Species))


# set plot switches to turn on or off various components
include_points = TRUE
include_lines = FALSE
include_density = TRUE
include_facet = TRUE


p +
list(
if(include_points){geom_point()},
if(include_lines){geom_line()},
if(include_facet){
      

# multi-line conditional elements can be included as a list
list(
facet_grid(rows = "Species"),
labs(subtitle = "This plot has been faceted, and colour has been removed"),
aes(colour = NULL)
)
      

},
if(include_density){geom_density2d()}) +
  

# additional elements common to all possible conditional combinations
# can be added as well
theme_minimal() +
labs(title = "Plot with conditional elements")

With the conditions as follows:

include_points = TRUE
include_lines = FALSE
include_density = TRUE
include_facet = TRUE

The following plot is generated:

Faceted plot with density and points

Setting include_facet = FALSE the following plot is generated:

Coloured plot with density - no facets