如果拥有一个主要使用数值的data.table,那么如何只转换列的子集并将它们放回到原始数据表中?一般来说,我不想将任何摘要统计信息作为单独的列添加,只需交换已转换的列。
假设我们有一个DT。它有1列名称和10列数字值。我有兴趣使用" scale"对于该数据表的每一行,基数R的函数,但仅适用于那10个数字列。
并对此进行扩展。如果我有一个包含更多列的数据表怎么办?我需要使用列名来告诉scale函数应用该函数的数据点?
使用常规data.frame我会这样做:
df[,grep("keyword",colnames(df))] <- t(apply(df[,grep("keyword",colnames(df))],1,scale))
我知道这看起来很麻烦但总是对我有用。但是,我无法在data.tables中找到一种简单的方法。
我会像这样想像data.tables:
dt[,grep("keyword",colnames(dt)) := scale(grep("keyword",colnames(dt)),center=F)]
但它没有。
编辑:
使用每行缩放版本更新列的另一个示例:
dt = data.table对象
dt[,grep("keyword",colnames(dt),value=T) := as.data.table(t(apply(dt[,grep("keyword",colnames(dt)),with=F],1,scale)))]
太糟糕了它需要&#34; as.data.table&#34;部分内部,因为apply函数的转置值是一个矩阵。也许data.table应该在更新列时自动将矩阵强制转换为data.tables?
答案 0 :(得分:2)
如果你需要的是真正按行扩展,你可以尝试分两步:
# compute mean/sd:
mean_sd <- DT[, .(mean(unlist(.SD)), sd(unlist(.SD))), by=1:nrow(DT), .SDcols=grep("keyword",colnames(DT))]
# scale
DT[, grep("keyword",colnames(DT), value=TRUE) := lapply(.SD, function(x) (x-mean_sd$V1)/mean_sd$V2), .SDcols=grep("keyword",colnames(DT))]
答案 1 :(得分:0)
# First lets take a look at the data in the columns:
DT[,.SD, .SDcols = grep("corrupt", colnames(DT))]`
单线解决方案版本1:使用magrittR和管道运算符:
DT[, (grep("keyword", colnames(DT))) := (lapply(.SD, . %>% scale(., center = F))),
.SDcols = grep("corrupt", colnames(DT))]
单行解决方案版本2:明确定义lapply的功能:
DT[, (grep("keyword", colnames(DT))) :=
(lapply(.SD, function(x){scale(x, center = F)})),
.SDcols = grep("corrupt", colnames(DT))]
修改-如果要按组进行修改,只需使用by =
DT[ , (grep("keyword", colnames(DT))) :=
(lapply(.SD, function(x){scale(x, center = F)}))
, .SDcols = grep("corrupt", colnames(DT))
, by = Grouping.Variable]
您可以验证:
# Verify that the columns have updated values:
DT[,.SD, .SDcols = grep("corrupt", colnames(DT))]
以上解决方案对于给出的狭窄示例显然适用。
作为一项公共服务,我会将其发布给仍在寻找
方式的任何人# You get a data.table called DT
DT <- as.data.table(df)
# Get the list of names
Reference.Cols <- grep("keyword",colnames(df))
# FOR PEOPLE who want to store both transformed and untransformed values.
# Create new column names
Reference.Cols.normalized <- Reference.Cols %>% paste(., ".normalized", sep = "")
#Define the function you wish to apply
# Where, normalize is just a function as defined in the question:
normalize <- function(X,
X.mean = mean(X, na.rm = TRUE),
X.sd = sd(X, na.rm = TRUE))
{
X <- (X - X.mean) / X.sd
return(X)
}
# Voila, the newly created set of columns the contain the transformed value,
DT[, (Reference.Cols.normalized) := lapply(.SD, normalize), .SDcols = Reference.Cols]
DT[, .SD, .SDcols = Reference.Cols.normalized]
DT[, .SD, .SDcols = Reference.Cols]
希望,对于那些在一段时间后返回查看代码的人来说,这种循序渐进/通用的方法可能会有所帮助。