![](/img/trans.png)
[英]Select subset of data.table columns based on observations in a given row
[英]data.table: transforming subset of columns with a function, row by row
擁有一個主要為數值的 data.table 怎么能只轉換列的子集並將它們放回原始數據表? 通常,我不想將任何匯總統計信息添加為單獨的列,只需交換轉換后的統計信息即可。
假設我們有一個 DT。 它有 1 列名稱和 10 列數值。 我有興趣為該數據表的每一行使用基數 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)))]
太糟糕了,它需要內部的“as.data.table”部分,因為來自 apply 函數的轉置值是一個矩陣。 也許 data.table 應該在更新列時自動將矩陣強制轉換為 data.tables?
如果您確實需要按行縮放,您可以嘗試分兩步進行:
# 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))]
# 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]
希望對於那些在一段時間后返回查看代碼的人來說,這種更逐步/通用的方法可能會有所幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.