【问题标题】:Can one get the grouping variables inside empty grouping in plyr ddply?可以在 plyr ddply 的空分组中获取分组变量吗?
【发布时间】:2020-04-30 12:14:38
【问题描述】:

假设我们有这样的数据:

library(plyr)

#some data
x = data.frame(
  letters = factor(c("a", "c"), levels = letters[1:4])
)

即,我们有一个未出现在数据中的因子的水平 b 和 d。我们可以遍历letters的组:

#loop inside
plyr::ddply(x, "letters", function(xx) {
  #do something here
  if (xx$letters == "b") print("do something")

  data.frame(
    count = nrow(xx)
  )
})

给我们:

  letters count
1       a     1
2       c     1

所以我们缺少 b 和 d 级别。然后我们添加drop = F 以不跳过它们:

plyr::ddply(x, "letters", .drop = F, function(xx) {
  #do something here
  #if (xx$letters == "b") print("do something")

  data.frame(
    count = nrow(xx)
  )
})

我们得到:

  letters count
1       a     1
2       b     0
3       c     1
4       d     0

但是,假设我们想根据字母组在循环内做一些事情。当我们得到空的 b 组时,我们想做一些事情。然而,我们不知道我们什么时候在里面。如果我们添加if (nrow(xx)==0) browser(),我们可以查看xx对象:

[1] letters
<0 rows> (or 0-length row.names)

但我们无法判断它是 b 还是 d。能查到吗?

【问题讨论】:

    标签: r plyr


    【解决方案1】:

    是的,它可以通过花哨的查找来完成。要解决这个问题,请在循环内调用 browser() 并检查环境中是否存在带有 ls() 的对象:

    Called from: .fun(piece, ...)
    Browse[1]> c
    Called from: .fun(piece, ...)
    Browse[1]> xx
    [1] letters
    <0 rows> (or 0-length row.names)
    Browse[1]> ls(all.names = T)
    [1] "xx"
    

    所以这里除了空的数据框片段(原始数据的子集)之外什么都没有。如果这里有一个隐藏的物体来指示这件作品,那就太好了,但是唉。但是,我们可以看看父环境,看看我们是否走运:

    Browse[1]> ls(all.names = T, envir = parent.frame(1))
    [1] "i"     "piece"
    Browse[1]> ls(all.names = T, envir = parent.frame(2))
     [1] "..."       ".data"     ".fun"      ".inform"   ".parallel" ".paropts"  ".progress" "do.ply"    "n"         "pieces"    "progress" 
    [12] "result"   
    

    好的,其中肯定有一些东西。可以使用get()mget() 一次获取多个:

    Browse[1]> mget(ls(envir = parent.frame(1)), envir = parent.frame(1))
    $i
    [1] 2
    
    $piece
    [1] letters
    <0 rows> (or 0-length row.names)
    
    Browse[1]> mget(ls(envir = parent.frame(2)), envir = parent.frame(2))
    $do.ply
    function (i) 
    {
        piece <- pieces[[i]]
        if (.inform) {
            res <- try(.fun(piece, ...))
            if (inherits(res, "try-error")) {
                piece <- paste(utils::capture.output(print(piece)), 
                    collapse = "\n")
                stop("with piece ", i, ": \n", piece, call. = FALSE)
            }
        }
        else {
            res <- .fun(piece, ...)
        }
        progress$step()
        res
    }
    <bytecode: 0x559669467ca8>
    <environment: 0x55966c7c6798>
    
    $n
    [1] 4
    
    $pieces
    $a
      letters
    1       a
    
    $b
    [1] letters
    <0 rows> (or 0-length row.names)
    
    $c
      letters
    1       c
    
    $d
    [1] letters
    <0 rows> (or 0-length row.names)
    
    
    $progress
    $progress$init
    function (x) 
    NULL
    <bytecode: 0x559669453cd0>
    <environment: 0x55966e5c8b50>
    
    $progress$step
    function () 
    NULL
    <bytecode: 0x559669453e58>
    <environment: 0x55966e5c8b50>
    
    $progress$term
    function () 
    NULL
    <bytecode: 0x559669453e58>
    <environment: 0x55966e5c8b50>
    
    
    $result
    $result[[1]]
    NULL
    
    $result[[2]]
    NULL
    
    $result[[3]]
    NULL
    
    $result[[4]]
    NULL
    

    所以我们看到parent.frame(1) 中的i 是当前子集计数,parent.frame(2) 中的片段名称具有我们想要的级别。把它们放在一起,我们可以得到当前的水平:

    plyr::ddply(x, "letters", .drop = F, function(xx) {
      #figure out the piece
      i = get("i", envir = parent.frame(1))
      levels = names(get("pieces", envir = parent.frame(1)))
      current_piece = levels[i]
    
      #do something
      if (current_piece == "b") print("this is the b empty group!") else print("This is not level b")
    
      data.frame(
        count = nrow(xx)
      )
    })
    

    导致:

    [1] "This is not level b"
    [1] "this is the b empty group!"
    [1] "This is not level b"
    [1] "This is not level b"
      letters count
    1       a     1
    2       b     0
    3       c     1
    4       d     0
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-11
      • 2021-09-19
      • 2018-07-30
      相关资源
      最近更新 更多