我想根据另一个数据表中的外部值更新数据表的某些指定列中的值。
我知道如何通过变量来做这个变量,但我想要一个更有效的解决方案,我可以自动化,也许使用lapply
更新:我的数据集(相当于下例中的mtcars
)包含其他我不想更新的列。
# Load library
library(data.table)
# load data
data(mtcars)
# create another Data Table which we'll use as external reference
# this table shows the number of decimals of those variables we want to modify in mtcars
var <- c("mpg","disp","hp")
Decimal <- c(1,3,2)
DT <- cbind.data.frame(var, Decimal)
# convert into data.table
setDT(DT)
setDT(mtcars)
mtcars[, mpg := mpg / 10 ^ DT[var=="mpg", Decimal] ]
mtcars[, disp := disp / 10 ^ DT[var=="disp", Decimal] ]
mtcars[, hp := hp / 10 ^ DT[var=="hp", Decimal] ]
此代码工作正常,它可以提供所需的结果。
mtcars
的第一行过去看起来像这样:
> mpg disp hp
> 1: 21.0 160 110
现在看起来像这样:
> mpg disp hp
> 1: 2.10 0.160 1.10
使用function
,lapply
等是否有更高效的解决方案?
答案 0 :(得分:4)
看起来Map()
会这样做
library(data.table)
## match 'DT$var' to the names of 'mtcars'
m <- chmatch(levels(DT$var)[DT$var], names(mtcars))
## update 'mtcars' with the desired operation
mtcars[, names(mtcars) := Map("/", .SD, 10 ^ DT$Decimal[m])]
## result
head(mtcars)
# mpg disp hp
# 1: 2.10 0.160 1.10
# 2: 2.10 0.160 1.10
# 3: 2.28 0.108 0.93
# 4: 2.14 0.258 1.10
# 5: 1.87 0.360 1.75
# 6: 1.81 0.225 1.05
或者,如果您想加快一点,我们可以使用.mapply()
代替Map()
来电话
.mapply(`/`, list(.SD, 10 ^ DT$Decimal[match(DT$var, names(mtcars))]), NULL)
答案 1 :(得分:4)
我们还可以将set
用于多个列。它非常有效,因为避免了[.data.table
的开销。我们遍历&#39; mtcars&#39;的列索引,并使用set
更改&#39; j&#39;指定的列。使用value
计算相应的&#39; mtcars&#39;带有&#39; DT $ Decimal&#39;的列元件。
for(j in seq_along(mtcars)){
set(mtcars, i=NULL, j=j, value=mtcars[[j]]/10^DT[,Decimal][j])
}
head(mtcars)
# mpg disp hp
#1: 2.10 0.160 1.10
#2: 2.10 0.160 1.10
#3: 2.28 0.108 0.93
#4: 2.14 0.258 1.10
#5: 1.87 0.360 1.75
#6: 1.81 0.225 1.05
编辑:根据OP的评论,假设我们没有对数据集进行子集化并希望保留所有列,同时转换&#39; var&#39;中指定的某些列,我们可以循环在&#39; var&#39;并使用set
更改&#39; var&#39;指定的列。在这里,我在转换为mtcars
后使用完整的data.table
数据集。
for(j in seq_along(var)){
set(mtcars, i=NULL, j=var[j], value=mtcars[[var[j]]]/10^DT[, Decimal][j])
}
head(mtcars)
# mpg cyl disp hp drat wt qsec vs am gear carb
#1: 2.10 6 0.160 1.10 3.90 2.620 16.46 0 1 4 4
#2: 2.10 6 0.160 1.10 3.90 2.875 17.02 0 1 4 4
#3: 2.28 4 0.108 0.93 3.85 2.320 18.61 1 1 4 1
#4: 2.14 6 0.258 1.10 3.08 3.215 19.44 1 0 3 1
#5: 1.87 8 0.360 1.75 3.15 3.440 17.02 0 0 3 2
#6: 1.81 6 0.225 1.05 2.76 3.460 20.22 1 0 3 1