首页 > 解决方案 > R data.table 遍历列以有条件地替换行值

问题描述

寻找应该是一个非常简单的解决方案。如果满足给定条件(小于零),我想有条件地替换一行中的值,并且我想对数百列(在示例中为 20 列)执行此操作,每列有 1.5 亿行。我正在尝试在堆栈中找到的每个解决方案的第七个小时,所以请不要将其标记为重复。:-)

数据:

library(data.table)
library(dplyr)
dt <- data.table(id=c(1:1000), x=rnorm(1:1000,60,20))

使用直观的循环创建新列:

## Create new variables
for(i in 50:70) {
  dt[, paste0("y", i) := i-x]
}

单列上的简单命令,效果很好:

dt$y60[dt$y60<0 ] <- 0

把它放在一个循环中,它会失败:

for(i in 50:70) {
  dt$y[i][dt$y[i]<0] <- 0
}

什么应该是一个简单的 DT 方法,没有运气:

for(i in 50:70) {
  dt[y[i]<0, y[i] := 0]
}

尝试一种ifelse()方法,没有运气:

for(i in 50:70) {
  dt$y[i] <- ifelse(dt$y[i] < 0, 0, dt$y[i])
}

首先尝试创建一个列表,然后使用set(),没有骰子:

list <- dt %>% dplyr:: select(starts_with("y"))
for(i in 50:70) {
  set(dt, i, list , 0)
}

我的生命掌握在你的手中,谢谢!!

标签: rdata.table

解决方案


选项 1 使用:=

dt[, (paste0("y", 50:70)) := lapply(.SD, function(x) {x[x<0] <- 0; x}), .SDcols=paste0("y", 50:70)]

选项 2 使用set

for (j in paste0("y", 50:70)) {
    set(dt, dt[,which(get(j) < 0)], j, 0)
}

数据:

library(data.table)
dt <- data.table(id=c(1:1000), x=rnorm(1:1000,60,20))
for(i in 50:70) {
    dt[, paste0("y", i) := i-x]
}

推荐阅读