我有data.table几个列(可以是动态数量的列),我想对其应用最小值。每列都有自己特定的最小值。
我的基本版本data.table如下所示:
library(data.table)
dt <- data.table(
urn = 1:10,
col1 = 5:14,
col2 = 11:20
)
Run Code Online (Sandbox Code Playgroud)
注意:我只包含了两列,其中的值需要具有代表的最小值。可能有更多的列,因此尝试动态地对此进行编码。
我的方法是嵌套lapply语句等,但我不知道如何在lapply函数中调用我的列。
min_vals <- c(10, 15)
my_cols <- grep("^col", colnames(dt), value = TRUE)
## First approach
dt[,
(my_cols) := lapply(min_vals, function(x) {
my_cols[my_cols < x] <- x
})]
## Second Approach
dt[,
(my_cols) := lapply(min_vals, function(x) {
ifelse(my_cols < x, x, my_cols)
})]
Run Code Online (Sandbox Code Playgroud)
目前,第一种方法将所有行设置为相应的min_vals,而不仅仅是min_vals. 第二种方法根本不起作用,反而出错。
所需的输出如下所示:
dt
# urn col1 col2
# <int> <int> <int>
# 1: 1 10 15
# 2: 2 10 15
# 3: 3 10 15
# 4: 4 10 15
# 5: 5 10 15
# 6: 6 10 16
# 7: 7 11 17
# 8: 8 12 18
# 9: 9 13 19
# 10: 10 14 20
Run Code Online (Sandbox Code Playgroud)
如果有一个解决方案允许动态匹配格式的列数,那就太好了col<number>。
我们可以使用Mapand 代替lapplyand,正如评论中的@Roland 指出的那样,i) 循环.SD作为第一个输入(.SDcols用指定mycols)并使用 ii) 更快,fielse而不是ifelse。
library(data.table)
dt[, (my_cols) := Map(\(x, m) fifelse(x < m, m, x),
.SD,
min_vals),
.SDcols = my_cols]
dt
#> urn col1 col2
#> 1: 1 10 15
#> 2: 2 10 15
#> 3: 3 10 15
#> 4: 4 10 15
#> 5: 5 10 15
#> 6: 6 10 16
#> 7: 7 11 17
#> 8: 8 12 18
#> 9: 9 13 19
#> 10: 10 14 20
Run Code Online (Sandbox Code Playgroud)
@Mwavu 建议在评论中pmax使用另一个不错的选择:fifelse
dt[, c(my_cols) := Map(\(x, y) pmax(x, y), .SD, min_vals), .SDcols = my_cols]
#> same result as above
Run Code Online (Sandbox Code Playgroud)
来自OP的数据
dt <- data.table(
urn = 1:10,
col1 = 5:14,
col2 = 11:20
)
min_vals <- c(10, 15)
my_cols <- grep("^col", colnames(dt), value = TRUE)
Run Code Online (Sandbox Code Playgroud)
创建于 2023-03-20,使用reprex v2.0.2