Necesito trazar múltiples definiciones de funciones explícitas para compararlas visualmente.

Considere la familia de funciones:

fun.1 <- function(x) { 1 / ( 0.01 + x) }
fun.2 <- function(x) { 1 / ( 0.1 + x) }
fun.3 <- function(x) { 1 / ( 0.3 + x) }

La idea es graficar el resultado de evaluar estas funciones en las siguientes entradas:

xs = c(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048)

Actualmente, mi código es:

library(ggplot2)
library(dplyr)

xs = c(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048)

fun.1 <- function(x) { 1 / ( 0.01 + x) }
fun.2 <- function(x) { 1 / ( 0.1 + x) }
fun.3 <- function(x) { 1 / ( 0.3 + x) }

base <- ggplot(data.frame(x = xs), aes(x=as.factor(x)))

base + theme_classic() +
       theme(
          legend.position = c(.95, .95),
          legend.justification = c("right", "top"),
          legend.box.just = "right",
          legend.margin = margin(6, 6, 6, 6)
          ) +
       geom_function(fun = fun.1, colour = "red") + 
       geom_function(fun = fun.2, colour = "blue") +
       geom_function(fun = fun.3, colour = "yellow") +
       scale_x_discrete(name = "Input",
                        breaks = xs) +
       scale_y_discrete(name = "Growth")

La trama resultante es esta

Ahora, esto se ve feo entre otras cosas, no puedo hacer que aparezca la leyenda y hay advertencias:

Multiple drawing groups in `geom_function()`. Did you use the correct `group`, `colour`, or `fill` aesthetics?
Multiple drawing groups in `geom_function()`. Did you use the correct `group`, `colour`, or `fill` aesthetics?
Multiple drawing groups in `geom_function()`. Did you use the correct `group`, `colour`, or `fill` aesthetics?

El estilo que intento conseguir es como este. Idealmente, los puntos deberían ser visibles y conectado por una curva continua.

La pregunta es, ¿cuál es la mejor manera de crear un gráfico con múltiples funciones con un estilo como este?

0
fulem 8 dic. 2020 a las 00:59

2 respuestas

La mejor respuesta

Puede simplemente lapply() sobre algo y si se agrega automáticamente al ggplot porque es una lista. Sin embargo, esto solo es útil si la salida del bucle de aplicación son cosas que ggplot entiende, como geoms.

El siguiente ejemplo asume que la función relevante se puede encontrar usando la estructura de nombres que proporcionó.

library(ggplot2)
library(dplyr)
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union

xs = c(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048)

fun.1 <- function(x) { 1 / ( 0.01 + x) }
fun.2 <- function(x) { 1 / ( 0.1 + x) }
fun.3 <- function(x) { 1 / ( 0.3 + x) }

ggplot(data.frame(x = xs), aes(x=x)) + 
  lapply(1:3, function(i) {
    fun_name <- paste0("fun.", i)
    fun <- get(fun_name)
    line <- geom_function(fun = fun,
                          aes(colour = fun_name))
    points <- geom_point(aes(y = fun(xs), colour = fun_name))
    list(line, points)
  }) +
  scale_x_log10(breaks = xs, name = "Input") +
  scale_y_continuous(name = "Growth") +
  theme_classic() +
  theme(
    legend.position = c(.95, .95),
    legend.justification = c("right", "top"),
    legend.box.just = "right",
    legend.margin = margin(6, 6, 6, 6)
  )

Creado el 2020-12-07 por el paquete reprex (v0.3.0)

Nota importante, mientras que su gráfico parece continuo en casi todos los sentidos, agrega la variante _discrete() de escalas de posición que no entiendo. En su lugar, convertí todo a numérico.

0
teunbrand 7 dic. 2020 a las 22:16

También puedes probar:

library(ggplot2)
#Plot
base <- ggplot(data.frame(x = xs), aes(x=as.factor(x)))
#Plot 2
base + theme_classic() +
  theme(
    legend.position = c(.95, .95),
    legend.justification = c("right", "top"),
    legend.box.just = "right",
    legend.margin = margin(6, 6, 6, 6)
  ) +
  stat_function(fun = fun.1, aes(colour = "fun.1"),geom = 'point',size=1) + 
  stat_function(fun = fun.1, aes(colour = "fun.1"),geom = 'line') + 
  stat_function(fun = fun.2, aes(colour = "fun.2"),geom='point',size=1) +
  stat_function(fun = fun.2, aes(colour = "fun.2"),geom = 'line') +
  stat_function(fun = fun.3, aes(colour = "fun.3"),geom = 'point',size=1) +
  stat_function(fun = fun.3, aes(colour = "fun.3"),geom = 'line') +
  scale_x_discrete(name = "Input",
                   breaks = xs) +
  scale_y_discrete(name = "Growth")+
  scale_color_manual(values = c('red','blue','yellow'))

Salida:

enter image description here

0
Duck 7 dic. 2020 a las 22:18