【问题标题】:How to vectorize this replacement operation?如何向量化这个替换操作?
【发布时间】:2013-12-28 18:03:05
【问题描述】:

我有一个数据集,需要根据另一个数据集的值进行封顶/修剪等。两个数据集具有相同的结构(列名等)。

将存储在另一个数据集中的转换应用于当前数据集的快速方法是什么?

样本数据:

#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

我很确定有一种更快的矢量化方法可以做到这一点。非常感谢任何意见。

【问题讨论】:

    标签: r for-loop vectorization apply


    【解决方案1】:

    一个选项:将你的逻辑写成一个接受向量和值的函数:

    myfun <- function(x, y) {
        x[is.na(x)] <- y
        x[x > y] <- y
        return (x)
    }
    

    然后使用mapplyx1 视为列列表(它有点像):

    mapply(myfun, x1, y1)
    

    您可以通过包装将其强制回data.frame

    data.frame(mapply(myfun, x1, y1))
    

    如果你愿意,也可以添加SIMPLIFY=FALSE...


    根据 cmets,Map 是一个更好的选择,因为它避免了一些打字和一些开销:

    as.data.frame(Map(myfun, x1, y1))
    

    【讨论】:

    • 是的,您需要SIMPLIFY = FALSE,否则某些列可能会转换为不同的类型。另请注意,as.data.frame(mapply(..., SIMPLIFY = FALSE)) 等价于较短的 as.data.frame(Map(...))
    • 我总是忘记MapReduce
    • 这是完美的。谢谢@贾斯汀
    【解决方案2】:

    这是使用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
    

    【讨论】:

      猜你喜欢
      • 2021-09-02
      • 2020-01-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多