【问题标题】:a faster way of running sapply in a for loop在 for 循环中运行 sapply 的更快方法
【发布时间】:2013-01-12 11:37:20
【问题描述】:

我正在尝试找到一种更快的方法来运行一个函数,它正在寻找一个时间段内每一天的中值。有没有比在 for 循环中运行 Sapply 更快的方法?

for(z in unique(as.factor(df$group))){
all[[z]]<- sapply(period, function(x) median(df[x == df$date & df$group==z, 'y']))
}

样本数据:

date<-as.Date("2011-11-01") + 
runif( 1000, 
       max=as.integer( 
           as.Date( "2012-12-31") - 
               as.Date( "2011-11-01")))
period<-as.Date(min(df$date):max(df$date), origin = "1970-01-01")
df <- data.frame(date=date, y = rnorm(1000), group=factor(rep(letters[1:4], each=250)))

【问题讨论】:

    标签: r for-loop sapply


    【解决方案1】:

    如果我理解正确,你想split by group 然后计算每个date 内的median。这是data.table 解决方案。

    编辑:问题出在数据集的date 格式上。它似乎报告了错误的唯一元素数量。所以,我不得不将它重铸为POSIXct 格式。

    df$date <- as.POSIXct(as.character(df$date), format="%Y-%m-%d")
    require(data.table)
    dt <- data.table(df)
    
    setkey(dt, "date")
    dt.out <- dt[, lapply(letters[1:4], 
              function(x) median(y[group == x])), by = date]
    

    这与 Victor 的输出相同。

    【讨论】:

    • 我需要组中每个因素的列(四列 + 一个日期列),而不是所有组的一列。
    • 这也给了我几天的多个值
    【解决方案2】:

    这是使用基本 R 函数 tapply 的解决方案

    tapply(df$y, df$date, median)
    

    更新。从您上面的评论来看,每个组需要一列吗?这也是单行:

    tapply(df$y, list(df$date, df$group), median)
    

    【讨论】:

    • 这里是您混淆的潜在来源。首先,让我的示例可重现 - 在 OP 代码的开头插入 set.seed(1)。然后,请比较length(unique(df$date))(给出1000)和length(unique(format(df$date, "%Y/%m/%d")))(给出391)。你明白为什么吗?出于某种原因,unique 不适用于 Date 类型。
    • 是的。 Date 对象可能存储两个具有相同打印表示但不相同的不同日期,这实际上很令人困惑:在x &lt;- as.Date(c(1.1, 1.0), origin = "1970-01-01") 之后,x[1] == x[2] 返回FALSE
    • 顺便说一句,tapply 正常工作的原因是因为它将第二个参数转换为因子,这会截断日期的小数部分。
    猜你喜欢
    • 2013-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-13
    • 2011-12-10
    • 2021-07-07
    • 1970-01-01
    相关资源
    最近更新 更多