在 R 中按因子绘制函数

Plotting functions by factor in R

我想按因素调用数据帧中的图,以便为每个因素(或因素组合)形成一个单独的图,其中包含所有相关行。

我可以使用 matplotplyr 包的组合以这种方式调用常规绘图。但是,我现在需要绘制函数,其系数是从数据帧中调用的。

一个简化的工作示例包含两个因子和三个系数。实际数据集很大,每个因素的行数各不相同。

df <- data.frame(fac_1 = c('A', 'A', 'B', 'B', 'B', 'C', 'C'),
             fac_2 = c('X', 'X', 'Y', 'X', 'X', 'Z', 'Y'), 
             param_1 = c(1, 2, 5, 3, 6, 1, 6),
             param_2 = c(3, 6, 6, 4, 5, 3, 4),
             param_3 = c(7, 8, 2, 6, 2, 6, 1))

示例函数(注意这是特定于第 1 行的)

curve_func <- function(x, y = 1) {
    df$param_1[y] +
    df$param_2[y] * x +
    df$param_3[y] * x^2
}

调用单个 curve

curve(expr = curve_func,
      from = 0,
      to = 5,
      type = "l")

恐怕我正在努力寻找从这里去哪里。我知道 add = T 参数可用于叠加多个 curves,但我还不知道如何在这种情况下使用它。

最后,我意识到我可以 'manually' 绘制每条曲线(即通过输入 x 值的精细序列将函数应用于每一行,然后进行 matplot y 对比 x),但我希望有更好的选择吗?

非常感谢您的帮助或指导。

我可以提供一个 ggplot2 答案,但不确定你是否想留在你提到的包中。

对于 ggplot2 中的分面特征来说,这听起来不错。我会尝试:

ggplot(dataframe, aes(x = x_var, y = y_var)) + 
  geom_smooth() +
  facet_grid(. ~ factor1)

您还可以使用 facet_wrap 以不同方式排列因子图。

在此处查看更多内容:http://www.cookbook-r.com/Graphs/Facets_(ggplot2)/

基地情节

如果你想留在基本情节,这个

curve_fct <- function(p1, p2, p3) {
  continue <- FALSE
  for (i in seq_along(p1)) {
    curve(p1[i] + p2[i] * x + p3[i] * x^2,
          from = 0,
          to = 5,
          type = "l",
          add = continue)
    continue = TRUE
  }
}

library(data.table)
setDT(df)[, curve_fct(param_1, param_2, param_3), keyby = .(fac_1, fac_2)]

将为每个 fac_1fac_2 的组合创建一个图,每个组合的曲线数量与参数集一样多。

编辑:带注释的底图

您还可以在图的标题中显示因素:

curve_fct2 <- function(txt, p1, p2, p3) {
  continue <- FALSE
  for (i in seq_along(p1)) {
    curve(p1[i] + p2[i] * x + p3[i] * x^2,
           from = 0,
           to = 5,
           type = "l",
           add = continue)
    continue = TRUE
  }
  title(main = txt)
  return(length(p1))
}
library(data.table)
setDT(df)[, curve_fct2(sprintf("Factors: %s, %s", fac_1, fac_2), 
                       param_1, param_2, param_3), 
          keyby = .(fac_1, fac_2)]

ggplot2

以类似的方式,您可以使用 ggplot2 创建多个图表。请注意包 polynom 的用法,这是一项额外的改进。

library(polynom)
library(ggplot2)

curve_fct_gg <- function(p1, p2, p3) {
  gg <- ggplot(data.frame(x = c(0, 5)), aes(x))
  for (i in seq_along(p1)) {
    # define polynomial function to be plotted
    p <- as.function(polynomial(c(p1[i], p2[i], p3[i])))
    gg <- gg + stat_function(fun = p)
  }
  print(gg)
  return(length(p1)) # to avoid empty data.table
}
setDT(df)[, curve_fct_gg(param_1, param_2, param_3), keyby = .(fac_1, fac_2)]

采纳 Mustafa 将 ggplot2 与分面结合使用的想法的不同方法。

这需要在绘图之前预先计算所有曲线的 y 值:

library(data.table)
library(polynom)
np <- 10 # number of points to plot curves
x <- seq(from = 0, to = 5, length.out = np)
plot_data <- setDT(df)[
  , param_set := seq_len(.N), keyby = .(fac_1, fac_2)][
    , .(x, y = as.function(polynomial(c(param_1, param_2, param_3)))(x)),
    keyby = .(fac_1, fac_2, param_set)]

绘图是用

完成的
library(ggplot2)
gg <- ggplot(plot_data, aes(x = x, y = y, group = param_set, colour = factor(param_set))) +
  geom_line() 
gg + facet_grid(fac_1 ~ fac_2)

创建:

或更紧凑:

gg + facet_wrap(~ fac_1 + fac_2)