【问题标题】:plyr does not return new variable after transform转换后 plyr 不返回新变量
【发布时间】:2011-04-14 19:05:41
【问题描述】:

我正在尝试学习如何在 R/plyr 中编写函数。我知道有更简单的方法来执行我在下面展示的操作,但这不是重点。

在下面的示例中,PLYR 不会将新变量返回到我的新数据框

library(plyr)
highab <-subset(baseball, ab >= 600)

testfunc1 <-function(x) {
    print(x) #just to show me that the vector does get into the function. Works fine.
    medianAB <- median(x)
    print(medianAB) #just to prove that medianAB was calculated correctly. Works fine   
}


baseball3 <-ddply(highab, .(id), transform, testfunc1(ab))
str(baseball3$medianAB) #No medianAB

我遗漏了什么明显的东西?

R version 2.12.2 (2011-02-25)
Platform: x86_64-pc-linux-gnu (64-bit)

locale:
 [1] LC_CTYPE=en_CA.UTF-8       LC_NUMERIC=C               LC_TIME=en_CA.UTF-8        LC_COLLATE=en_CA.UTF-8    
 [5] LC_MONETARY=C              LC_MESSAGES=en_CA.UTF-8    LC_PAPER=en_CA.UTF-8       LC_NAME=C                 
 [9] LC_ADDRESS=C               LC_TELEPHONE=C             LC_MEASUREMENT=en_CA.UTF-8 LC_IDENTIFICATION=C       

attached base packages:
[1] grid      splines   stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] foreign_0.8-42  ggplot2_0.8.9   proto_0.3-9.1   reshape_0.8.4   plyr_1.4.1      rms_3.3-0       Hmisc_3.8-3    
[8] survival_2.36-5 stringr_0.4    

loaded via a namespace (and not attached):
[1] cluster_1.13.3  lattice_0.19-23 tools_2.12.2   

【问题讨论】:

    标签: r plyr


    【解决方案1】:

    只需进行两次更改

    1. 去掉函数内部的打印命令,这样就返回了中位数
    2. 按照 Joshua 的建议添加 medianAB = testfunc1(ab)

    你已经完成了!

    这是带有输出的简化代码

    library(plyr)
    highab <-subset(baseball, ab >= 600)
    baseball3 <-ddply(highab, .(id), transform, medianAB = median(ab))
    summary(baseball3$medianAB)
    

    最小。第一曲。中位数平均第三曲。
    最大限度。 600.0 612.0 621.5 623.1 631.5 677.0

    【讨论】:

    • 我认为 #1 也是必需的,但 print(medianAB) 会从函数返回 medianAB,所以你只需要 #2。
    • @joshua mmmm 你是对的。想知道当我刚刚应用 #2 并出现错误时出了什么问题。
    • 在函数调用成功之前指定新变量。谢谢大家。例如'baseball3
    【解决方案2】:

    对不起。我误解了这个问题。

    ?transform。您需要将所需的新变量指定为 tag=value 对。所以你需要类似的东西

    baseball3 <- ddply(highab, .(id), transform, medianAB=testfunc1(ab))
    

    【讨论】:

    • 感谢 Joshua,但两种方法都不起作用。这就是奇怪的地方。
    • @John:对不起,我真的应该在提交之前测试我的答案...:-/
    【解决方案3】:

    起初我喜欢将派生列添加到 data.frame 的习惯用法,但我发现 transform() 的使用速度非常慢,非常大的集合。

    ddply() 中使用lambda 形式并随后调用合并merge() 会更好吗?时机似乎值得:

        > library(plyr)
        > highab <-subset(baseball, ab >= 600)
        > 
        > system.time( 
        +   baseball3.lambda <-merge(highab, 
        +     ddply(highab, .(id), 
        +       function(u) data.frame(medianAB = median(u$ab)))), FALSE)
           user  system elapsed 
          0.336   0.000   0.336 
        > 
        > system.time( 
            baseball3.orig <- ddply(highab, .(id), 
              transform, medianAB = median(ab)), FALSE)
           user  system elapsed 
          0.640   0.000   0.641 
        > 
        > summary(baseball3.lambda$medianAB)
           Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
          600.0   612.0   621.5   623.1   631.5   677.0 
        > summary(baseball3.orig$medianAB)
           Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
          600.0   612.0   621.5   623.1   631.5   677.0 
    

    十分之三秒可能看起来不多,但它将执行时间减半。通过选择整个baseball 数据集,改进会更大。

    【讨论】:

    • Re '不可接受的慢远大集合'评论,您是否尝试过 data.table 及其 := 运算符通过引用添加列?
    • 不,我没有尝试过data.table,尽管我知道它在许多情况下都很快。实际上我想找到/弄清楚的是如何合并这两种方法,ddply 的 split-apply-reduce 与data.table 的速度改进。
    • 不幸的是,您必须更改为 data.table 语法才能获得速度优势:DT[i,j,by]
    • 在 data.frames 上调整 plyr 方法以充分利用 data.table 快速索引难道不是有意义的吗?毕竟data.table 是一种底层基础设施改进,而不是解决状态问题的高级方法......
    • data.table 是一种高级方法。你读过 15 个(独立)crantastic reviews吗?
    猜你喜欢
    • 1970-01-01
    • 2013-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-16
    • 2018-09-10
    • 2018-02-21
    • 2018-04-04
    相关资源
    最近更新 更多