R 如何将函数映射为仅应用于数据帧中的某些行?

R 如何将函数映射为仅应用于数据帧中的某些行?,r,purrr,R,Purrr,我有一个函数,我只想迭代数据集中的某些行,然后将结果保存在数据集中的一个变量中 例如,假设我有这样的设置: library(tidyverse) add_one <- function(vector, x_id){ return(vector[x_id] + 1) } test <- data.frame(x = c(1,2,3,4), y = c(1,2,3,4), run_on = c(TRUE,FALSE,TRUE,FALSE)) test 因此,我要做的是迭代数据帧

我有一个函数,我只想迭代数据集中的某些行,然后将结果保存在数据集中的一个变量中

例如,假设我有这样的设置:

library(tidyverse)

add_one <- function(vector, x_id){
  return(vector[x_id] + 1)
}

test <- data.frame(x = c(1,2,3,4), y = c(1,2,3,4), run_on = c(TRUE,FALSE,TRUE,FALSE))
test
因此,我要做的是迭代数据帧,并将y列设置为将函数add_one()应用于x列的结果,该函数仅适用于run_on为TRUE的行。我希望最终结果如下所示:

>  x y run_on
>1 1 2   TRUE
>2 2 2  FALSE
>3 3 4   TRUE
>4 4 4  FALSE
add_one_if <- function(vector, x_id, y_id, run_on_id){
    if(vector[run_on_id]){
        return(add_one(vector,x_id))}
    else{
        return(vector[x_id])
    }
}

test$y <- apply(test, 1, add_one_if, x_id = 1, y_id = 2, run_on_id = 3)
我已经能够使用apply()在所有行上迭代函数。例如:

test$y <- apply(test,1,add_one,x_id = 1)
test

>  x y run_on
>1 1 2   TRUE
>2 2 3  FALSE
>3 3 4   TRUE
>4 4 5  FALSE
测试$y x y运行
>1 1 2正确
>2 3错误
>3 3 4正确
>4.5错误
但这也将函数应用于第2行和第4行,这是我不希望看到的。我怀疑可能有某种方法可以使用::purrr中的map()函数版本来实现这一点,这就是我将这篇文章标记为这样的原因

实际上,我正在使用这种过程对一个大型数据集进行多次重复迭代,因此我需要自动且干净地完成。如有任何帮助或建议,将不胜感激

更新

我设法找到了解决办法。这里提供的一些解决方案在我的玩具示例中确实有效,但没有扩展到我实际使用的更复杂的函数。最终的效果与tmfmnk的建议类似。我只是将原始函数包装在另一个函数中,该函数包含一个if语句,用于确定是否应用原始函数。因此,为了扩展我的玩具示例,我的解决方案如下所示:

>  x y run_on
>1 1 2   TRUE
>2 2 2  FALSE
>3 3 4   TRUE
>4 4 4  FALSE
add_one_if <- function(vector, x_id, y_id, run_on_id){
    if(vector[run_on_id]){
        return(add_one(vector,x_id))}
    else{
        return(vector[x_id])
    }
}

test$y <- apply(test, 1, add_one_if, x_id = 1, y_id = 2, run_on_id = 3)

add_one_if您的真实案例可能比这允许的更复杂,但为什么不使用ifelse呢

test$y <- ifelse(test$run_on,add_one(test,x),y)

test$y您的实际情况可能比这更复杂,但为什么不使用ifelse呢

test$y <- ifelse(test$run_on,add_one(test,x),y)
test$y您还可以执行以下操作:

add_one <- function(data, vector, x_id, n, is.true = c(TRUE, FALSE)) {  
 if (is.true) {
  return(data[[vector]] + (data[[x_id]]) * n)
 } else {
  return(data[[vector]] + (!data[[x_id]]) * n)
 }
}   

add_one(test, vector = "y", x_id = "run_on", 1, is.true = TRUE)

[1] 2 2 4 4

add_one(test, vector = "y", x_id = "run_on", 5, is.true = FALSE)

[1] 1 7 3 9
添加一个您还可以执行以下操作:

add_one <- function(data, vector, x_id, n, is.true = c(TRUE, FALSE)) {  
 if (is.true) {
  return(data[[vector]] + (data[[x_id]]) * n)
 } else {
  return(data[[vector]] + (!data[[x_id]]) * n)
 }
}   

add_one(test, vector = "y", x_id = "run_on", 1, is.true = TRUE)

[1] 2 2 4 4

add_one(test, vector = "y", x_id = "run_on", 5, is.true = FALSE)

[1] 1 7 3 9

add_one您不需要使用
purrr
,直到您将相同的函数应用于多个列。因为您只想修改一列,但根据条件,您可以使用
mutate()
+
case\u when()


在将相同的函数应用于多个列之前,您不需要使用
purr
。因为您只想修改一列,但根据条件,您可以使用
mutate()
+
case\u when()


带有(测试,y+运行)
;)如果jcr实际上只是向列中添加一个,那么这是一个聪明的解决方案。然而,听起来这只是一个例子,在这种情况下,这不会推广到其他函数。
使用(test,y+run_on)
)如果jcr实际上只是向列中添加一个,那么这是一个聪明的解决方案。然而,听起来这只是一个例子,在这种情况下,这不会推广到其他函数。不幸的是,这不起作用,因为y和run_on的列不是r环境中的对象——它们只在dataframe中。作为一个base::函数,ifelse()不够聪明,无法解决这个问题,并返回一个错误到
找不到对象“y”
的调子,现在无法测试它,但在那种情况下不会测试$y工作吗?还有,第二个选项呢?不幸的是,这不起作用,因为y和run_on的列不是r环境中的对象——它们只在数据帧中。作为一个base::函数,ifelse()不够聪明,无法解决这个问题,并返回一个错误到
找不到对象“y”
的调子,现在无法测试它,但在那种情况下不会测试$y工作吗?还有,第二种选择呢?