最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

r - Add number of counts per factor level to a looped plot - Stack Overflow

programmeradmin3浏览0评论

I have a dataframe like this ->

df = data.frame(c("LALO","LALO", "AMGP", "AMGP", "WRSA", "WRSA", "SNOW", "SNOW"),
                c(4.3, 2.5, 1.5, 1.2, 0.4, 0.2, 0.1, 0.05))
colnames(df) = c("sp_code","ind_km2")

df <- mutate(df, sp_code = factor(sp_code))

# df table :
sp_code ind_km2
1    LALO    4.30
2    LALO    2.50
3    AMGP    1.50
4    AMGP    1.20
5    WRSA    0.40
6    WRSA    0.20
7    SNOW    0.10
8    SNOW    0.05

I am using a loop to plot ind_km2 for each species :

sp_code <- levels(unique(df$sp_code))

    for (i in seq_along(sp_code)) {
  species <- sp_code[i]
  plot2 <- df %>% 
    ggplot(aes(x=sp_code, y=ind_km2, fill=sp_code)) +
    geom_violin(data = filter(df, sp_code == species), scale = "width", show.legend = FALSE) +
    stat_summary(data = filter(df, sp_code == species), fun.y=mean, geom="point", shape=23, size=4, fill = "black", show.legend = FALSE)
  print(plot2)
} 

I want to add the number of observations for each plot. I've searched online for solutions, but they either gave me errors or the filter is not working correctly.

I've tried using stat_summary with a function :

# Function
add_n <- function(y, upper_limit = (df %>%
                          select(sp_code, ind_km2) %>%
                          filter(sp_code == species) %>%
                          summarise(mean = mean(ind_km2))) * 1.15) {
  return( 
    data.frame(
      y = 0.95 * upper_limit,
      label = paste('n =', length(df), '\n')
    )
  )
}

# Add it to loop 

for (i in seq_along(sp_code)) {
  species <- sp_code[i]
plot2 <- df %>%
  ggplot(aes(x=sp_code, y=ind_km2, fill=sp_code)) +
  geom_violin(data = filter(df, sp_code == species), scale = "width", show.legend = FALSE) +
  stat_summary(data = filter(df, sp_code == species), fun.y=mean, geom="point", shape=23, size=4, fill = "black", show.legend = FALSE)+
  stat_summary(
    fun.data = add_n,
    geom = "text", 
    fun.y = median,
    hjust = 0.5,
    vjust = 0.9)
print(plot2)
}

This gave me an error (geom_text()` requires the following missing aesthetics: y), which I tried to fix with while looking online but couldn't find a solution that worked for me.

How can I either fix this error, or either use something else to have the number of observations for each level in my plots ?

(Thank you !)

I have a dataframe like this ->

df = data.frame(c("LALO","LALO", "AMGP", "AMGP", "WRSA", "WRSA", "SNOW", "SNOW"),
                c(4.3, 2.5, 1.5, 1.2, 0.4, 0.2, 0.1, 0.05))
colnames(df) = c("sp_code","ind_km2")

df <- mutate(df, sp_code = factor(sp_code))

# df table :
sp_code ind_km2
1    LALO    4.30
2    LALO    2.50
3    AMGP    1.50
4    AMGP    1.20
5    WRSA    0.40
6    WRSA    0.20
7    SNOW    0.10
8    SNOW    0.05

I am using a loop to plot ind_km2 for each species :

sp_code <- levels(unique(df$sp_code))

    for (i in seq_along(sp_code)) {
  species <- sp_code[i]
  plot2 <- df %>% 
    ggplot(aes(x=sp_code, y=ind_km2, fill=sp_code)) +
    geom_violin(data = filter(df, sp_code == species), scale = "width", show.legend = FALSE) +
    stat_summary(data = filter(df, sp_code == species), fun.y=mean, geom="point", shape=23, size=4, fill = "black", show.legend = FALSE)
  print(plot2)
} 

I want to add the number of observations for each plot. I've searched online for solutions, but they either gave me errors or the filter is not working correctly.

I've tried using stat_summary with a function :

# Function
add_n <- function(y, upper_limit = (df %>%
                          select(sp_code, ind_km2) %>%
                          filter(sp_code == species) %>%
                          summarise(mean = mean(ind_km2))) * 1.15) {
  return( 
    data.frame(
      y = 0.95 * upper_limit,
      label = paste('n =', length(df), '\n')
    )
  )
}

# Add it to loop 

for (i in seq_along(sp_code)) {
  species <- sp_code[i]
plot2 <- df %>%
  ggplot(aes(x=sp_code, y=ind_km2, fill=sp_code)) +
  geom_violin(data = filter(df, sp_code == species), scale = "width", show.legend = FALSE) +
  stat_summary(data = filter(df, sp_code == species), fun.y=mean, geom="point", shape=23, size=4, fill = "black", show.legend = FALSE)+
  stat_summary(
    fun.data = add_n,
    geom = "text", 
    fun.y = median,
    hjust = 0.5,
    vjust = 0.9)
print(plot2)
}

This gave me an error (geom_text()` requires the following missing aesthetics: y), which I tried to fix with while looking online but couldn't find a solution that worked for me.

How can I either fix this error, or either use something else to have the number of observations for each level in my plots ?

(Thank you !)

Share Improve this question asked Feb 16 at 15:30 MagMag 315 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 2

I want to add the number of observations for each plot.

Adapted data (added another observation for "LALO") and moved factor() inside data.frame().

 df0 = data.frame(sp_code = factor(c("LALO","LALO", "AMGP", "AMGP", "WRSA", "WRSA", "SNOW", "SNOW", "LALO")),
                  ind_km2 = c(4.3, 2.5, 1.5, 1.2, 0.4, 0.2, 0.1, 0.05, 1.7))

(1) You could use count in ggplot2::geom_text(). Avertising ggplot2::facet_wrap().

 library(ggplot2)
 df0 |>
   ggplot(aes(x = sp_code, y = ind_km2, fill = sp_code)) +
   geom_violin() + 
   facet_wrap(~sp_code, scales = 'free') +
   geom_text(aes(x = stage(sp_code, after_stat = Inf), 
                 y = after_stat(Inf), 
                 label = after_stat(sprintf('n=%s', count))), 
             stat = 'count', hjust = 1, vjust = 1)


(2) If you really want a plot for each level of sp_code, what should we do with the colour filling?

 l = split(df0, ~sp_code)
 n = length(l)
 col = palette.colors(n, palette = 'Set 1')
 lapply(seq(n), \(i) {
     l[[i]] |>
       ggplot(ggplot2::aes(x = sp_code, y = ind_km2)) +
       geom_violin(fill = col[i]) + 
       geom_text(aes(x = stage(sp_code, after_stat = Inf), 
                     y = after_stat(Inf), 
                     label = after_stat(sprintf('n=%s', count))), 
                 stat = 'count', hjust = 1, vjust = 1)
   })

发布评论

评论列表(0)

  1. 暂无评论