【问题标题】:R nested for loop to write multiple functions and plot themR嵌套for循环编写多个函数并绘制它们
【发布时间】:2016-08-08 05:57:46
【问题描述】:

这是我的数据:

color   a   b
red     3   1.3
blue    9   1.8
purple  13  1.2
green   4   1.1
orange  7   0.9
yellow  6   2.1
brown   7   1.8

对于每一行,我想编写一个名为“fun_color”的函数,格式如下:y = a*(x^b)

(a 和 b 是每一行的 data$a 和 data$b 列的值。x 是函数的域。)

我认为我应该按照以下内容编写一个嵌套的 for 循环:

for (i in dt$color) 
  {(paste("fun_",i, sep = "")) = function(x)
    for (a in dt$a) 
      {a*x}
    }

但是,我,一个相对的 R 新手,不能完全让这个 for 循环工作。

然后我想在同一个图上绘制这 10 个方程中的每一个。我想我应该在这里写另一个 for 循环,比如:

plot(fun_red)
for (i in function_list) {
  plot(i, add=TRUE)}

有什么帮助吗?谢谢!

【问题讨论】:

  • 啊,抱歉,应该是 y = a*(x^b)。 a 和 b 是 data$a 和 data$b 列的值。 x 是我要写的函数的域。

标签: r function for-loop plot


【解决方案1】:

选择一系列x 值,并使用 sapply 对其进行迭代。无需多次调用绘图函数,只需使用matplot

s <- seq(.2,5,by =.2)
matplot(s,t(sapply(s, function(x) dt$a*(x)^dt$b)),
        type = "l", lty = "solid", lwd = 2, col = dt$color, ylab = "y", xlab = "x")

【讨论】:

  • 但是,matplot 是一个包装函数,它在内部使用 for 循环,“多次”调用绘图函数。
  • 我知道,但它在自动生成绘图限制方面肯定有其好处。
【解决方案2】:

是的,使用for 循环。但是,请使用 curve 来绘制函数。

plot.new()
plot.window(xlim = c(0, 5), ylim = c(0, 200))
for (i in seq_len(nrow(DF))) curve(DF$a[i] * (x ^ DF$b[i]), 
                                   add = TRUE, col = as.character(DF$color[i]),
                                   lwd = 2)
axis(1)  
axis(2)

【讨论】:

    【解决方案3】:

    或者,我们可以使用apply 而不是for 循环来绘制函数。首先,让我们读入数据和要绘制的值的范围。

    dt <- read.table(text="color   a   b
    red     3   1.3
    blue    9   1.8
    purple  13  1.2
    green   4   1.1
    orange  7   0.9
    yellow  6   2.1
    brown   7   1.8", header=T)
    
    # vector for x values
    x1 <- 0
    x2 <- 1
    n <- 100
    x <- seq(x1, x2, by = ((x2-x1)/n))
    

    然后,我们绘制一个空白空间,将在其中绘制函数曲线。请注意,我们在 max.y 变量中计算 y 轴所需的最大值。

    max.y <- dt[which.max(rowSums(dt[,2:3])),2] * (x2 ^ dt[which.max(rowSums(dt[,2:3])),3])
    
    plot(x1, type="n", xlim=c(x1,x2), ylim=c(x1, max.y), xlab="x", ylab="a*(x^b)")
    

    最后,我们根据数据中的规范绘制线条。

    apply(dt, 1, FUN=function(dt.row) 
        lines(x, as.numeric(dt.row[2]) * (x ^ as.numeric(dt.row[3])), col=dt.row[1]))
    

    基准测试

    根据 Roland 和 sayaa 的 cmets,这是性能比较。来自 Roland 和 sayaa 的全部答案被输入到各自的函数中,从这里开始的所有内容都从 x1 变量定义到 nya() 函数。

    library(microbenchmark)
    microbenchmark(roland(dt))
    Unit: milliseconds
           expr      min      lq    mean   median       uq      max neval
     roland(dt) 18.09634 18.4124 19.2258 18.67313 19.17735 35.42943   100
    microbenchmark(shayaa(dt=dt))
    Unit: milliseconds
                expr      min       lq     mean   median       uq      max neval
     shayaa(dt = dt) 10.85788 11.04311 11.44358 11.22057 11.51216 18.19182   100
     microbenchmark(nya(dt=dt))
     Unit: milliseconds
              expr      min       lq     mean  median       uq      max neval
      nya(dt = dt) 18.26883 18.61892 19.02823 18.8229 19.18054 25.41353   100
    

    我会得出结论,在这种情况下,性能不是一个关键问题。用户可以根据个人喜好选择一种方法,并使用绘图大小(x1、x2、max.y)的动态选项对其进行修改。

    【讨论】:

    • system.time 不是对需要 2 毫秒系统时间的东西进行基准测试的方法。请改用microbenchmark
    【解决方案4】:

    以下不使用 for 循环来创建函数,而是使用根据作为参数给出的颜色返回不同函数的函数。这样做的好处是不使用assignget

    fun_col <- function(col) {
      a <- dt$a[dt$color == col]
      b <- dt$b[dt$color == col]
      function(x) a*x^b
    }
    
    for (col in dt$color) {
    
      plot(fun_col(col), add = TRUE)
    
    }
    

    【讨论】:

    • 投反对票来宣传assignget。您应该改用list
    • 我打算添加等效的列表,但由于某种原因,它变得很奇怪,我正在写一个问题来澄清这个问题。
    • 编辑:我删除了分配并得到“解决方案”,因为我意识到它主要是出于错误的原因
    猜你喜欢
    • 2017-07-31
    • 2019-08-29
    • 2018-09-30
    • 1970-01-01
    • 2017-08-13
    • 2021-09-15
    • 2015-10-15
    • 2021-10-27
    • 2021-11-15
    相关资源
    最近更新 更多