R中的条件if语句
Conditional if statement in R
我想知道如何根据其他列的值填充 data.frame 或 data.table 中的列。
例如:
data.table(a = c(1:5), b = c(5:1), c = rep("",5))
a b c
1 5
2 4
3 3
4 2
5 1
我想将 c 填充到:
- 表示"More"如果"a"大于"b"
- "Less" 如果 "a" 小于 "b"
- "相等则相等
如下:
a b c
1 5 "Less"
2 4 "Less"
3 3 "Equal"
4 2 "More"
5 1 "More"
我知道这可以通过带有多个 if 语句的 for 循环来完成,但是我有一个非常大的数据集,我想使用 "Apply" 系列函数来完成。
如有任何帮助,我们将不胜感激。
我们可以使用数值方法根据逻辑向量(a > b
和a==b
)创建唯一值,转换为factor
,得到numeric
存储通过转换为 numeric
的值,将其替换为 vector
(c("Less", "More", "Equal")
) 中的元素并将其分配 (:=
) 为 'c'.
dt1[, c :=c("Less", "More", "Equal")[as.numeric(factor(1+2*(a>b) + 4*(a==b)))]]
dt1
# a b c
#1: 1 5 Less
#2: 2 4 Less
#3: 3 3 Equal
#4: 4 2 More
#5: 5 1 More
或者我们可以使用嵌套 ifelse
来获得预期的输出。
dt1[, c:= ifelse(a>b, "More", ifelse(a<b, "Less", "Equal"))]
或者另一种选择是使用 Reduce/max.col/pmax
获取数字索引并将其替换为第一种方法中所示的字符向量。
dt1[, c:= c("Equal", "Less", "More")[pmax(max.col(.SD),
3*Reduce(`==`, .SD))], .SDcols = a:b]
数据
dt1 <- data.table(a = c(1:5), b = c(5:1), c = rep("",5))
根据我的测试,这是一个非常高效的方法,而且并不过分复杂:
dt1[, c := c("less","equal","more")[max.col(setDT(.(a < b, a==b, a > b)))] ]
使用 interaction
的另一种选择,它在简化代码方面与我所能做的一样好:
dt1[, c := c("equal","less","more")[interaction(a < b, a > b)] ]
# a b c
#1: 1 5 less
#2: 2 4 less
#3: 3 3 equal
#4: 4 2 more
#5: 5 1 more
这是有效的,因为 interaction
将 return 两种比较的四种可能性:
FALSE.FALSE
= 两者都不 TRUE
,在这种情况下意味着不大于或小于,因此等于
TRUE.FALSE
= 第一个 TRUE
,因此少
FALSE.TRUE
= 第二个 TRUE
,因此更多
TRUE.TRUE
= 两者都 TRUE
,理论上不可能,除了低于误差容限的边缘情况。
我想知道如何根据其他列的值填充 data.frame 或 data.table 中的列。
例如:
data.table(a = c(1:5), b = c(5:1), c = rep("",5))
a b c
1 5
2 4
3 3
4 2
5 1
我想将 c 填充到:
- 表示"More"如果"a"大于"b"
- "Less" 如果 "a" 小于 "b"
- "相等则相等
如下:
a b c
1 5 "Less"
2 4 "Less"
3 3 "Equal"
4 2 "More"
5 1 "More"
我知道这可以通过带有多个 if 语句的 for 循环来完成,但是我有一个非常大的数据集,我想使用 "Apply" 系列函数来完成。
如有任何帮助,我们将不胜感激。
我们可以使用数值方法根据逻辑向量(a > b
和a==b
)创建唯一值,转换为factor
,得到numeric
存储通过转换为 numeric
的值,将其替换为 vector
(c("Less", "More", "Equal")
) 中的元素并将其分配 (:=
) 为 'c'.
dt1[, c :=c("Less", "More", "Equal")[as.numeric(factor(1+2*(a>b) + 4*(a==b)))]]
dt1
# a b c
#1: 1 5 Less
#2: 2 4 Less
#3: 3 3 Equal
#4: 4 2 More
#5: 5 1 More
或者我们可以使用嵌套 ifelse
来获得预期的输出。
dt1[, c:= ifelse(a>b, "More", ifelse(a<b, "Less", "Equal"))]
或者另一种选择是使用 Reduce/max.col/pmax
获取数字索引并将其替换为第一种方法中所示的字符向量。
dt1[, c:= c("Equal", "Less", "More")[pmax(max.col(.SD),
3*Reduce(`==`, .SD))], .SDcols = a:b]
数据
dt1 <- data.table(a = c(1:5), b = c(5:1), c = rep("",5))
根据我的测试,这是一个非常高效的方法,而且并不过分复杂:
dt1[, c := c("less","equal","more")[max.col(setDT(.(a < b, a==b, a > b)))] ]
使用 interaction
的另一种选择,它在简化代码方面与我所能做的一样好:
dt1[, c := c("equal","less","more")[interaction(a < b, a > b)] ]
# a b c
#1: 1 5 less
#2: 2 4 less
#3: 3 3 equal
#4: 4 2 more
#5: 5 1 more
这是有效的,因为 interaction
将 return 两种比较的四种可能性:
FALSE.FALSE
= 两者都不TRUE
,在这种情况下意味着不大于或小于,因此等于TRUE.FALSE
= 第一个TRUE
,因此少FALSE.TRUE
= 第二个TRUE
,因此更多TRUE.TRUE
= 两者都TRUE
,理论上不可能,除了低于误差容限的边缘情况。