【问题标题】:Split data frame, apply function, and return results in a nested list拆分数据框,应用函数,并在嵌套列表中返回结果
【发布时间】:2012-07-18 10:10:59
【问题描述】:

我的问题标题几乎与dlplyplyr 包)描述一致,“嵌套”部分除外。

让我用一个例子来解释:

library(plyr)
res <- dlply(mtcars, c("gear", "carb"), identity)
head(res, 2)
# $`3.1`
#                 mpg cyl  disp  hp drat    wt  qsec vs am gear carb
# Hornet 4 Drive 21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1
# Valiant        18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1
# Toyota Corona  21.5   4 120.1  97 3.70 2.465 20.01  1  0    3    1
# 
# $`3.2`
#                    mpg cyl disp  hp drat    wt  qsec vs am gear carb
# Hornet Sportabout 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2
# Dodge Challenger  15.5   8  318 150 2.76 3.520 16.87  0  0    3    2
# AMC Javelin       15.2   8  304 150 3.15 3.435 17.30  0  0    3    2
# Pontiac Firebird  19.2   8  400 175 3.08 3.845 17.05  0  0    3    2

如您所见,输出是一个列表,其中名称(键)是我用于拆分数据的两个变量的串联,例如"3.1"(gear = 3, carb = 1) 的密钥。

相反,我希望我的结果是一个嵌套列表,以便可以通过两组键访问元素,一组键用于我的每个拆分变量:res[["3"][["1"]]

周围有什么东西,不一定来自plyr 包,可以实现这个吗?我希望答案可以推广到任意数量的拆分变量。此外,尽管我的示例使用了 identity 函数,但我可以应用任何函数也很重要,这只会导致数据的拆分。谢谢你的建议。

【问题讨论】:

    标签: r list plyr


    【解决方案1】:

    我自己提出了一个解决方案,它使用递归:

    nested.dlply <- function(df, by, fun, ...) {
    
       require(plyr)
    
       if (length(by) == 1) {
          dlply(df, by, fun, ...)
       } else {
          dlply(df, by[1], nested.dlply, by[-1], fun, ...)
       }
    }
    

    这里有几个例子:

    nested.dlply(mtcars, c("gear", "carb"), identity)
    # $`3`
    # $`3`$`1`
    #                     mpg cyl  disp  hp drat    wt  qsec vs am gear carb
    # Hornet 4 Drive 21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1
    # Valiant        18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1
    # Toyota Corona  21.5   4 120.1  97 3.70 2.465 20.01  1  0    3    1
    # 
    # $`3`$`2`
    #                    mpg cyl disp  hp drat    wt  qsec vs am gear carb
    # Hornet Sportabout 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2
    # Dodge Challenger  15.5   8  318 150 2.76 3.520 16.87  0  0    3    2
    # AMC Javelin       15.2   8  304 150 3.15 3.435 17.30  0  0    3    2
    # Pontiac Firebird  19.2   8  400 175 3.08 3.845 17.05  0  0    3    2
    # [...]
    
    nested.dlply(mtcars, c("gear", "carb"), head, 2)
    # $`3`
    # $`3`$`1`
    #                 mpg cyl disp  hp drat    wt  qsec vs am gear carb
    # Hornet 4 Drive 21.4   6  258 110 3.08 3.215 19.44  1  0    3    1
    # Valiant        18.1   6  225 105 2.76 3.460 20.22  1  0    3    1
    # 
    # $`3`$`2`
    #                    mpg cyl disp  hp drat   wt  qsec vs am gear carb
    # Hornet Sportabout 18.7   8  360 175 3.15 3.44 17.02  0  0    3    2
    # Dodge Challenger  15.5   8  318 150 2.76 3.52 16.87  0  0    3    2
    # [...]
    

    我怀疑这是否非常有效,但它确实有效。我仍然欢迎你的建议。理想情况下,我希望某些包已经实现了它。

    【讨论】:

    • 我不确定你是否看到this post,但Brian Diggs 在那里提供了plyr 解决方案:dlply(mtcars, .(gear), dlply, .(carb)) 等等,用于更多嵌套。正如在那个问题上所讨论的那样,这种嵌套的数据结构可能不是最方便使用的。
    • 谢谢@mrdwab。我认为推广 Brian Diggs 建议的嵌套 dlply 调用的唯一方法是使用上面的递归。您提供的链接确实帮助我缩短了代码(已编辑)。
    【解决方案2】:

    嵌套split怎么样?

    temp = lapply(split(mtcars, mtcars$gear), function(x) split(x, x$carb))
    temp[["3"]]["1"]
    # $`1`
    #                 mpg cyl  disp  hp drat    wt  qsec vs am gear carb
    # Hornet 4 Drive 21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1
    # Valiant        18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1
    # Toyota Corona  21.5   4 120.1  97 3.70 2.465 20.01  1  0    3    1
    

    【讨论】:

    • 谢谢,但它并不能完全解决我的问题,请阅读我的问题的结尾:我需要将它推广到任意数量的拆分变量(不仅仅是两个),并且它需要应用一个函数(不仅仅是拆分)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-02-15
    • 2017-05-27
    • 2020-10-27
    • 2014-06-12
    • 2021-03-15
    • 1970-01-01
    • 2018-03-21
    相关资源
    最近更新 更多