使用 if-else 逻辑计算数据框中新向量的不同值

using if-else logic to compute different values of new vectors in a data frame

这是一个名为 results 的数据框:

results <- data.frame(cbind(tot=c(3,4,3,2,1,1,3,0),
                              a=c(0,1,2,2,0,1,1,0),
                              b=c(3,3,1,0,1,0,2,0)))

每行包含一个 tot 的值,等于 ab 的总和。

我需要创建向量 a_prop_tweakb_prop_tweak 并将它们附加到此数据框。如果 ab 大于零,则这两个新变量以一种方式计算(对于 a,我将 a 除以 tot 并添加 0.025;对于 b,我将 b 除以 tot 并减去 0.025)。如果只有 a 为零(b_prop_tweak=b/ntota_prop_tweak=0),我会以不同的方式计算这些值。如果只有 b 为零,则应以另一种方式计算这两个变量(a_prop_tweak=a/ntotb_prop_tweak=0)。如果 ab 均为零,则新变量也应为零。

修改后的数据框 result 应该是这样的:

results <- data.frame(cbind(tot=c(3, 4,     3,         2, 1, 1, 3,         0),
                              a=c(0, 1,     2,         2, 0, 1, 1,         0),
                              b=c(3, 3,     1,         0, 1, 0, 2,         0),
                   a_prop_tweak=c(0, 0.275, 0.6916667, 1, 0, 1, 0.3583333, 0),
                   b_prop_tweak=c(1, 0.725, 0.3083333, 0, 1, 0, 0.6416667, 0)))

请注意,除非 tot 等于零,否则 a_prop_tweakb_prop_tweak 总和为 1。

我为完成此任务而编写的错误代码正在以我不希望的方式工作:

if(results$a > 0 && results$b > 0){
  results$a_prop_tweak <- results$a / results$tot + 0.025
  results$b_prop_tweak <- results$b / results$tot - 0.025
}else if(results$a > 0 && results$b == 0){
  results$a_prop_tweak <- results$a / results$tot
  results$b_prop_tweak <- 0
}else if(results$a == 0 && results$b > 0){
  results$a_prop_tweak <- 0
  results$b_prop_tweak <- results$b / results$tot
}else{
  results$a_prop_tweak <- 0
  results$b_prop_tweak <- 0
}

这是输出,似乎可以正确计算 b_prop_tweak(当 totab 均为零时除外):

> results
  tot a b a_prop_tweak b_prop_tweak ab_prop_chk
1   3 0 3            0    1.0000000           1
2   4 1 3            0    0.7500000           1
3   3 2 1            0    0.3333333           1
4   2 2 0            0    0.0000000           1
5   1 0 1            0    1.0000000           1
6   1 1 0            0    0.0000000           1
7   3 1 2            0    0.6666667           1
8   0 0 0            0          NaN           0

我显然是在错误地思考这个问题。有什么想法吗?

有时仔细检查代码会有所帮助。您正在评估向量,而不是您尝试完成的每行评估。通过这样做,您总是会在 if 语句的这一部分结束:

else if(results$a == 0 && results$b > 0){
  results$a_prop_tweak <- 0
  results$b_prop_tweak <- results$b / results$tot

有很多方法可以做您想做的事,我稍后会尝试 post 其中一种。只是想告诉你出了什么问题。

> results$a
[1] 0 1 2 2 0 1 1 0
> results$b
[1] 3 3 1 0 1 0 2 0
> results$a > 0 && results$b
[1] FALSE
> results$a > 0 && results$b
[1] FALSE
> results$a == 0 && results$b > 0
[1] TRUE

正如其他人指出的那样,尝试使用 results$a>0 之类的语句测试返回的内容。您将查看整个列,而不是一次只查看每一行。我会通过将列子集化为您感兴趣的特定情况来处理此问题:

#Create the data frame
results <- data.frame(cbind(tot=c(3,4,3,2,1,1,3,0),
                            a=c(0,1,2,2,0,1,1,0),
                            b=c(3,3,1,0,1,0,2,0)))

#create the new columns and initialize to 0
results$a_prop_tweak <- 0
results$b_prop_tweak <- 0


#Deal with cases where both a and b are >0
results$a_prop_tweak[results$a >0 & results$b >0] <- results$a[results$a >0 & results$b >0] /
  results$tot[results$a >0 & results$b >0] +0.025
results$b_prop_tweak[results$a >0 & results$b >0] <- results$b[results$a >0 & results$b >0] /
  results$tot[results$a >0 & results$b >0] -0.025

#If a>0 but b==0:
results$a_prop_tweak[results$a >0 & results$b == 0] <- results$a[results$a >0 & results$b == 0] /
  results$tot[results$a >0 & results$b == 0]
#No need for a b_prop_tweak since it's already 0 by default

#If a==0 and b>0
results$b_prop_tweak[results$a == 0 & results$b > 0] <- results$b[results$a == 0 & results$b > 0] /
  results$tot[results$a == 0 & results$b > 0]

dplyr 的解决方案,使用 rowwisecase_when

library(dplyr)

results %>% 
  rowwise() %>% 
  mutate( a_prop_tweak=case_when( 
               a > 0 & b > 0 ~ (a/tot) + 0.025, 
               a == 0 & b != 0 ~ 0, 
               a != 0 & b == 0 ~ a/tot, 
               a == 0 & b == 0 ~ 0 ), 
          b_prop_tweak=case_when( 
               a > 0 & b > 0 ~ (b/tot) - 0.025, 
               a == 0 & b != 0 ~ b/tot, 
               a != 0 & b == 0 ~ 0, 
               a == 0 & b == 0 ~ 0 ) ) %>% 
  ungroup()
# A tibble: 8 × 5
    tot     a     b a_prop_tweak b_prop_tweak
  <dbl> <dbl> <dbl>        <dbl>        <dbl>
1     3     0     3        0            1    
2     4     1     3        0.275        0.725
3     3     2     1        0.692        0.308
4     2     2     0        1            0    
5     1     0     1        0            1    
6     1     1     0        1            0    
7     3     1     2        0.358        0.642
8     0     0     0        0            0