【问题标题】:if else condition in ggplot to add an extra layerif else 条件在ggplot中添加一个额外的层
【发布时间】:2014-05-19 20:50:27
【问题描述】:

假设我想在 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 的对象不等于表达式“无值”。

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() geom_line:
stat_identity:
position_identity: (width = NULL, height = NULL)

【问题讨论】:

  • 为什么不直接改变顺序:p + geom_line() + if(tmp.data[1]!="no value"){ geom_point()}
  • @shadow。这仅在我的第二层是函数中的最后一个参数时才有效。如果我添加更多参数,例如:+ theme(panel.background = element_rect(fill = "lightskyblue2")) 它不再起作用

标签: r if-statement ggplot2


【解决方案1】:

这是使用 ggplot2 2.1.0 完成的。我认为您可以完全按照 OP 的要求做,只需切换括号,以便它们包含整个 if 语句。

这是一个添加水平线的示例,具体取决于 SwtichT 还是 F。一、其中条件为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()

现在,同样的事情,但条件是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()

【讨论】:

  • 好像不能在{里面使用+,所以如果你想有条件地在一个ggplot中添加多个东西,我相信你需要再添加一个if语句(对于您添加到绘图中的每个对象,在它自己的 {) 内。
  • 您不能在{ 中使用+,但如果您有多个步骤,则可以将所有内容放入list{if(Switch)list(geom_hline(yintercept=15), geom_hline(yintercept = 13))}
【解决方案2】:

您看到的是语法错误。我能想到的最稳健的方法是:

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

因此,您将对象 p 组合成一个序列,仅当 if 语句产生 TRUE 时才添加 geom_point()

【讨论】:

  • 如果尝试 facet_wrap,此解决方案将不起作用。我收到错误: seq.default(min, max, by = by) 中的错误:'from' must be afinite number
【解决方案3】:

按照ggplot2 book,您可以创建一个返回列表的函数。任何 NULL 组件都将被忽略。

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)

reprex package (v0.3.0) 于 2020 年 2 月 25 日创建

【讨论】:

    【解决方案4】:
    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
    

    但也许这更像你真正想要的?

    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
    

    【讨论】:

      猜你喜欢
      • 2013-09-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-21
      • 1970-01-01
      • 2020-06-27
      • 1970-01-01
      相关资源
      最近更新 更多