我有一个数据集,需要根据另一个数据集的值进行上限/修剪等。两个数据集都具有相同的结构(列名等)。
将存储在其他数据集中的转换应用于当前数据集的快速方法是什么?
示例数据:
#generate sample data & set some values to NA
#this is the dataset that has variables that need to be trimmed
x1 <- data.frame(a=rep(11:20), b=rep(41:50))
x1[2,1] <- NA
x1
#a vector containing values to trim to (in this case, say 75th percentile)
y1 <- apply(x1, 2, function(x) quantile(x, 0.75, na.rm=T))
y1
#I am doing this inside a loop
for (i in 1:ncol(x1)){
x1[is.na(x1[[i]]),] <- y1[i] #if missing, set to some value
x1[x1[[i]] > y1[i], i] <- y1[i] #if larger than 75th pctl, set to some value
}
x1
我很确定有一种更快的矢量化方式来做到这一点。我非常感谢任何投入。
答案 0 :(得分:1)
一个选项:将您的逻辑编写为一个带矢量和值的函数:
myfun <- function(x, y) {
x[is.na(x)] <- y
x[x > y] <- y
return (x)
}
然后使用mapply
将x1
视为列的列表(它的类别):
mapply(myfun, x1, y1)
你可以通过包裹它来强制它回到data.frame
:
data.frame(mapply(myfun, x1, y1))
如果您愿意,还可以添加SIMPLIFY=FALSE
根据评论,Map
是一个更好的选择,因为它避免了一些打字,可能还有一些开销:
as.data.frame(Map(myfun, x1, y1))
答案 1 :(得分:1)
这是使用data.table
包的另一个选项。 data.table
速度非常快,语法强大,但缺点是需要学习新的语法。
library(data.table)
x1 <- data.frame(a=rep(11:20), b=rep(41:50))
x1[2,1] <- NA
# Convert data.frame to data.table.
DT <- data.table(x1)
# Put your desired operations into a function, for clarity/tidiness.
update_vals <- function(x, prob=0.75) {
xcut <- quantile(x, probs=prob, na.rm=TRUE)
x[is.na(x) | x > xcut] <- xcut
return(x)
}
# Use lapply and data.table syntax to 'loop' over columns.
DT2 = DT[, lapply(.SD, update_vals)]
DT2
# a b
# 1: 11 41.00
# 2: 18 42.00
# 3: 13 43.00
# 4: 14 44.00
# 5: 15 45.00
# 6: 16 46.00
# 7: 17 47.00
# 8: 18 47.75
# 9: 18 47.75
# 10: 18 47.75