R中使用ifelse函数时未返回向量

4
我写了一个有些奇怪的函数,它应该只返回一个具有两个值的向量。
例如,如果您输入33,则应返回(30,40)。
这没有比这更简单的了。
return_a_range <- function(number){
    ans <-  ifelse(  (30  <= number & number <= 40), c(30, 40),
                     (ifelse( (40  < number  & number  <= 50), c(40, 50),
                              (ifelse( (50  < number  & number  <= 60), c(50, 60),
                                       (ifelse( (60  < number  & number  <= 70), c(60, 70),
                                                (ifelse( (70  < number  & number  <= 80), c(70, 80),
                                                         (ifelse( (80  < number  & number  <= 100), c(80, 100),                      
                                                                           ans <- c("NA"))))))))))))
    return(ans)}

return_a_range(33)

为什么这仅返回30?我为什么没有收到c(30, 40)?为什么R决定仅返回向量中第一个位置的值? 编辑
尽管大多数回复关注于(理所当然地!)批评我写烂了的ifelse语句,但我认为最好回答实际问题的是下面评论中的@MrFick。

9
ifelse() 函数返回的向量长度始终与你输入的向量长度相同(即 number 的长度)。在每个“case”中不能返回多个元素。但是建议您使用 findIntervalcut 函数,而不是像这样使用 ifelse - MrFlick
我不知道 car::recode 怎么适用于这个。 - Rich Scriven
2
这个需要用到哪些包?x <- 33; 10 * floor(x / 10) + c(0, 10) - rawr
@CarlWitthoft:我刚刚了解到switch不能进行向量化,这令人惊讶和不幸。 - tumultous_rooster
1
@MattO'Brien 然后看一下 ?vectorize - Carl Witthoft
显示剩余2条评论
3个回答

4
您可以使用以下代码:

您可以直接使用:

> c(floor(33 / 10), ceiling(33 / 10))*10
[1] 30 40

或者作为一个函数 - 感谢@Khashaa在评论中提供的不错修改:
f <- function(x) if(abs(x) >= 100) NA else c(floor(x / 10), floor(x/10) + 1)*10
f(44)
#[1] 40 50

f(40)
#[1] 40 50

这种函数比多重嵌套的ifelse语句更有效率。
我最初忽略了你想要在输入值为40时返回30-40(我以为你想要返回40-50,这是上述函数所做的)。因此,这是一个稍微复杂一些的函数,应该可以实现这种行为:
ff <- function(x) {
  if (abs(x) >= 100L) {
    NA 
  } else {
    y <- floor(x / 10L) * 10L
    if (x %% 10L == 0L) {
      c(y - 10L, y) 
    } else {
      c(y, y + 10L)
    }
  }
}

并且在实际操作中:

ff(40)
#[1] 30 40
ff(45)
#[1] 40 50

如果您有一个数字向量,您可以对其进行lapply/sapply操作:

( x <- sample(-100:100, 3, F) )
#[1]  73  89 -97

lapply(x, ff)
#[[1]]
#[1] 70 80
#
#[[2]]
#[1] 80 90
#
#[[3]]
#[1] -100  -90

或者
sapply(x, ff)
#     [,1] [,2] [,3]
#[1,]   70   80 -100
#[2,]   80   90  -90

我同意,有些情况需要检查,例如 f(40) 返回 c(40, 40) 而不是 c(30, 40) - tumultous_rooster

2

这里有另一种使用%/%的变体,可以适用于f2(40)的情况(但可能在其他地方失败?)

f2 <- function(x) if(abs(x) >= 100) NA else c(x %/% 10, (x + 10) %/% 10) * 10
f2(40)
## [1] 40 50

OP想要在输入40时返回c(30, 40) - 起初我也没有注意到这一点。 - talat

1
如果您真的想按照自己的方式使用函数,而不是采用docendo的答案(对于这个问题我看不出为什么要这样做),您可以按照以下步骤操作(以防将来需要进行类似的操作):
return_a_range <- function(number){
  ans <-  ifelse(  (30  <= number & number <= 40), a<-c(30, 40),
                   (ifelse( (40  < number  & number  <= 50), a<-c(40, 50),
                            (ifelse( (50  < number  & number  <= 60), a<-c(50, 60),
                                     (ifelse( (60  < number  & number  <= 70), a<-c(60, 70),
                                              (ifelse( (70  < number  & number  <= 80), a<-c(70, 80),
                                                       (ifelse( (80  < number  & number  <= 100), a<-c(80, 100),                      
                                                                a <- c("NA"))))))))))))
  return(a)}

> return_a_range(33)
[1] 30 40

> return_a_range(62)
[1] 60 70

我所做的唯一事情就是在每个ifelse中将向量保存在变量a中。

ans <- 是否仍应该存在? - tumultous_rooster
感谢您的评论。我错过了“ans”。它应该像其他部分一样变成“a”。我已在答案中进行了更改。 - LyzandeR

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接