尝试在R中编写分段函数

尝试在R中编写分段函数,r,R,我对R相当陌生,想写一个分段函数,我的代码不起作用,如果你能帮忙,请评论: a<-rnorm(1000) ifelse(0<a & a<=.3,C=sqrt(30*a),NA) ifelse(.3<a & a<=.7,C=5*a+15/10),NA) ifelse(.7<a & a<=1,c=8-sqrt(-30*a+30),NA) a三个问题: 当直接用作函数调用参数列表的一部分时,=不是赋值运算符,

我对R相当陌生,想写一个分段函数,我的代码不起作用,如果你能帮忙,请评论:

   a<-rnorm(1000)

   ifelse(0<a & a<=.3,C=sqrt(30*a),NA)
   ifelse(.3<a & a<=.7,C=5*a+15/10),NA)
   ifelse(.7<a & a<=1,c=8-sqrt(-30*a+30),NA)
a三个问题:

  • 当直接用作函数调用参数列表的一部分时,
    =
    不是赋值运算符,而是命名参数的语法
  • 与其尝试在
    ifelse()
    函数调用参数列表中赋值,不如赋值结果
  • 您当前正在执行三个不同的计算。真的,你只想表演一个。要解决此问题,您需要嵌套您的呼叫:
  • 这两种解决方案都有一个不幸的副作用,即由于NaN值(由计算负数平方根的代码引起)而引发警告。有关解决此问题的方法,请参阅。

    三个问题:

  • 当直接用作函数调用参数列表的一部分时,
    =
    不是赋值运算符,而是命名参数的语法
  • 与其尝试在
    ifelse()
    函数调用参数列表中赋值,不如赋值结果
  • 您当前正在执行三个不同的计算。真的,你只想表演一个。要解决此问题,您需要嵌套您的呼叫:

  • 这两种解决方案都有一个不幸的副作用,即由于NaN值(由计算负数平方根的代码引起)而引发警告。有关解决此问题的方法,请参阅。

    在10之后的第二个
    ifelse
    语句中有一个额外的括号。您可以删除它或添加另一对。

    在10之后的第二个
    ifelse
    语句中有一个额外的括号。您可以删除它或添加另一对。

    关于问题中的代码:

  • 作业应该在ifelse外部完成,而不是在内部完成

  • ifelse将首先计算所有值的两个支腿,因此如果传递负数
    a
    ,它将尝试获取负数的平方根,即使未选择该支腿。因此,最好避免在此处完全使用
    ifelse

  • 嵌套的ifelse可能很难遵循

  • 下面的解决方案避免了
    ifelse
    。第一个使用if。。。其他的与
    ifelse
    不同,它只计算实际使用的支腿。它只适用于标量,但我们可以使用
    Vectorize
    将我们编写的标量函数转换为接受向量的函数

    第二种解决方案将介于0和1之间的
    a
    的值与其他值分开,这样我们就不会尝试取负数的平方根,因此主计算中不涉及NA。它使用成语cond1*y1+cond2*y2+。。。其中y1,y2。。。是数值非NA表达式和cond1、cond2、。。。是相互排斥的条件。对于每个向量分量,只有一个条件为真,因此R将相应的表达式乘以1,保持不变,其他条件乘以0,消除它们

    1)使用if/else并将其矢量化。这即使适用于a的负值,也不会发出警告,否则可能会由于负平方根而发出警告,并且不会使用包

    f <- Vectorize(function(a)
      if (0 < a & a <= 0.3) sqrt(30 * a)
      else if (0.3 < a & a <= 0.7) 5 * a + 15 / 10
      else if (0.7 < a & a <= 1) 8 - sqrt(-30 * a + 30)
      else NA)
    
    a <- seq(0, 1, 0.01)
    c <- f(a)
    
    head(c)
    ## [1]        NA 0.5477226 0.7745967 0.9486833 1.0954451 1.2247449
    
    tail(c)
    ## [1] 6.775255 6.904555 7.051317 7.225403 7.452277 8.000000
    
    plot(c ~ a, type = "l")
    

    f关于问题中的代码:

  • 作业应该在ifelse外部完成,而不是在内部完成

  • ifelse将首先计算所有值的两个支腿,因此如果传递负数
    a
    ,它将尝试获取负数的平方根,即使未选择该支腿。因此,最好避免在此处完全使用
    ifelse

  • 嵌套的ifelse可能很难遵循

  • 下面的解决方案避免了
    ifelse
    。第一个使用if。。。其他的与
    ifelse
    不同,它只计算实际使用的支腿。它只适用于标量,但我们可以使用
    Vectorize
    将我们编写的标量函数转换为接受向量的函数

    第二种解决方案将介于0和1之间的
    a
    的值与其他值分开,这样我们就不会尝试取负数的平方根,因此主计算中不涉及NA。它使用成语cond1*y1+cond2*y2+。。。其中y1,y2。。。是数值非NA表达式和cond1、cond2、。。。是相互排斥的条件。对于每个向量分量,只有一个条件为真,因此R将相应的表达式乘以1,保持不变,其他条件乘以0,消除它们

    1)使用if/else并将其矢量化。这即使适用于a的负值,也不会发出警告,否则可能会由于负平方根而发出警告,并且不会使用包

    f <- Vectorize(function(a)
      if (0 < a & a <= 0.3) sqrt(30 * a)
      else if (0.3 < a & a <= 0.7) 5 * a + 15 / 10
      else if (0.7 < a & a <= 1) 8 - sqrt(-30 * a + 30)
      else NA)
    
    a <- seq(0, 1, 0.01)
    c <- f(a)
    
    head(c)
    ## [1]        NA 0.5477226 0.7745967 0.9486833 1.0954451 1.2247449
    
    tail(c)
    ## [1] 6.775255 6.904555 7.051317 7.225403 7.452277 8.000000
    
    plot(c ~ a, type = "l")
    

    f谢谢,它成功了!!非常感谢我希望base R有这样的案例陈述。。。我发现嵌套的
    ifelse
    更难可视化(因此也更难维护),更不用说
    ifelse
    不安全的责任了。从长远来看,我发现
    dplyr::case_when
    data.table::fcase
    要好得多,不过我还是希望它能在base R的某个地方找到…@r2evans是的,base R奇怪地缺少一个有用的
    开关
    表达式(实际的
    switch()
    函数非常糟糕)。谢谢你,它成功了!!非常感谢我希望base R有这样的案例陈述。。。我发现嵌套的
    ifelse
    更难可视化(因此也更难维护),更不用说
    ifelse
    不安全的责任了。从长远来看,我发现
    dplyr::case_when
    data.table::fcase
    要好得多,尽管我还是希望它能在base R的某个地方找到…@r2evans是的,base R奇怪地缺少一个有用的
    switch
    表达式(实际的
    switch()
    函数是
    f <- Vectorize(function(a)
      if (0 < a & a <= 0.3) sqrt(30 * a)
      else if (0.3 < a & a <= 0.7) 5 * a + 15 / 10
      else if (0.7 < a & a <= 1) 8 - sqrt(-30 * a + 30)
      else NA)
    
    a <- seq(0, 1, 0.01)
    c <- f(a)
    
    head(c)
    ## [1]        NA 0.5477226 0.7745967 0.9486833 1.0954451 1.2247449
    
    tail(c)
    ## [1] 6.775255 6.904555 7.051317 7.225403 7.452277 8.000000
    
    plot(c ~ a, type = "l")
    
    f2 <- function(x) {
      ix <- x > 0 & x <= 1
      a <- x[ix]
      replace(NA * x, ix, (0 < a & a <= 0.3) * sqrt(30 * a) +
        (0.3 < a & a <= 0.7) * (5 * a + 15 / 10) +
        (0.7 < a & a <= 1) * (8 - sqrt(-30 * a + 30)))
    }
    
    # test
    c2 <- f(a)
    identical(c, c2)
    ## [1] TRUE