使用 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
的值,等于 a
和 b
的总和。
我需要创建向量 a_prop_tweak
和 b_prop_tweak
并将它们附加到此数据框。如果 a
和 b
大于零,则这两个新变量以一种方式计算(对于 a
,我将 a
除以 tot
并添加 0.025
;对于 b
,我将 b
除以 tot
并减去 0.025
)。如果只有 a
为零(b_prop_tweak=b/ntot
;a_prop_tweak=0
),我会以不同的方式计算这些值。如果只有 b
为零,则应以另一种方式计算这两个变量(a_prop_tweak=a/ntot
;b_prop_tweak=0
)。如果 a
和 b
均为零,则新变量也应为零。
修改后的数据框 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_tweak
和 b_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(当 tot
、a
和 b
均为零时除外):
> 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
的解决方案,使用 rowwise
和 case_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
这是一个名为 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
的值,等于 a
和 b
的总和。
我需要创建向量 a_prop_tweak
和 b_prop_tweak
并将它们附加到此数据框。如果 a
和 b
大于零,则这两个新变量以一种方式计算(对于 a
,我将 a
除以 tot
并添加 0.025
;对于 b
,我将 b
除以 tot
并减去 0.025
)。如果只有 a
为零(b_prop_tweak=b/ntot
;a_prop_tweak=0
),我会以不同的方式计算这些值。如果只有 b
为零,则应以另一种方式计算这两个变量(a_prop_tweak=a/ntot
;b_prop_tweak=0
)。如果 a
和 b
均为零,则新变量也应为零。
修改后的数据框 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_tweak
和 b_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(当 tot
、a
和 b
均为零时除外):
> 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
的解决方案,使用 rowwise
和 case_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