首页 > 解决方案 > 使用循环或应用根据条件仅覆盖数据框中变量的某些值

问题描述

我想编写一个循环或应用R来根据条件仅覆盖变量的某些值。这是一个示例数据框:

df <- data.frame(
  state = c("MA","CO","TX"),
  random_numeric = c(26,28,4),
  var1 = c(3,0,0),
  var2 = c(3,1,5),
  var3 = c(0,1,0),
  prelim_row_sum = c(6,2,5)
)
df
  state random_numeric var1 var2 var3 prelim_row_sum
1    MA             26    3    3    0              6
2    CO             28    0    1    1              2
3    TX              4    0    5    0              5

df中,我只想替换,中的第一个值,或者如果它等于一半var1,则将其替换为零。因此,正确的循环或应用将仅将前三个和前 1 替换为零。我在示例数据框中有和变量,以显示我的较大数据框中还有其他字符和数字变量。因此,解决方案对我不起作用。当然,我可以一个一个地做这个:var2var3prelim_row_sumrandom_numericstatedplyracross

df[1,3] <- 0
df[2,4] <- 0
df$final_row_sum = rowSums(df[3:5])
df
  state random_numeric var1 var2 var3 prelim_row_sum final_row_sum
1    MA             26    0    3    0              6             3
2    CO             28    0    0    1              2             1
3    TX              4    0    5    0              5             5

但我真的很感谢有关循环、应用或函数的帮助,以便我可以在更大的、非程式化的数据帧上执行此操作。谢谢!

标签: rloopsapply

解决方案


这是处理 with 的一种方法apply。我允许一点通用性,因为您必须输入要应用此函数的列。最后有一个包装函数,因此您可以将这些值设置为零,然后创建final_row_sum列。

  state = c("MA","CO","TX"),
  random_numeric = c(26,28,4),
  var1 = c(3,0,0),
  var2 = c(3,1,5),
  var3 = c(0,1,0),
  prelim_row_sum = c(6,2,5)
)

my_func <- function(x){
  value_to_zero <- which(
    x[1:(length(x)-1)] == (x[length(x)]/2)
  )
  if(length(value_to_zero) > 0){
    x[value_to_zero[1]] <- 0
  }
  return(x)
}

new_df <- df

cols_to_fix <- c("var1", "var2", "var3", "prelim_row_sum")

new_df[,cols_to_fix] <- t(
  apply(
    new_df[,cols_to_fix],
    1,
    my_func
  )
)

new_df$final_row_sum <- rowSums(new_df[,cols_to_fix[-length(cols_to_fix)]])

new_df

  state random_numeric var1 var2 var3 prelim_row_sum final_row_sum
1    MA             26    0    3    0              6             3
2    CO             28    0    0    1              2             1
3    TX              4    0    5    0              5             5

all_in_one <- function(x, cols){
  
  my_func <- function(x){
    value_to_zero <- which(
      x[1:(length(x)-1)] == (x[length(x)]/2)
    )
    if(length(value_to_zero) > 0){
      x[value_to_zero[1]] <- 0
    }
    return(x)
  }
  
  
  x[,cols] <- t(
    apply(
      x[,cols],
      1,
      my_func
    )
  )
  
  x$final_row_sum <- rowSums(x[,cols[-length(cols)]])
  
  return(x)
  
}

answer <- all_in_one(df, c("var1", "var2", "var3", "prelim_row_sum"))

  state random_numeric var1 var2 var3 prelim_row_sum final_row_sum
1    MA             26    0    3    0              6             3
2    CO             28    0    0    1              2             1
3    TX              4    0    5    0              5             5

推荐阅读