在 'summarise(data, lhs = rhs)' 调用中:有没有办法将 rhs 的属性传递给 lhs?

问题描述

以下几行突出显示了该问题。属性在许多情况下会被转移,但不是在最后一种情况下,这是一个常见的“总结”用例。非常感谢任何帮助!

suppressWarnings(suppresspackageStartupMessages(library(dplyr)))

obj <- c(12,13,51)
attributes(obj)<- list(cv = c(3,4,2))
print(obj)
#> [1] 12 13 51
#> attr(,"cv")
#> [1] 3 4 2
## 'obj' has an attribute
print(attributes(obj))
#> $cv
#> [1] 3 4 2

tbl <- tibble::tibble(col = obj)
print(tbl$col)
#> [1] 12 13 51
#> attr(,"cv")
#> [1] 3 4 2
## attributes are retained by the col obj was assigned to
print(attributes(tbl$col))
#> $cv
#> [1] 3 4 2

foo <- function(x){
  # to be called within 'summarise()'
  o <- sum(x)
  attributes(o)<- list(cvv = o*2)
  return(o)
}
# produces values with attributes
print(foo(7))
#> [1] 7
#> attr(,"cvv")
#> [1] 14

tbl2 <- tbl %>% 
  summarise(z = foo(col))
# with one single row,attributes are transferred to tbl2
print(attributes(tbl2$z))
#> $cvv
#> [1] 152

tbl2 <- tbl %>% 
  group_by(col) %>% 
  summarise(z = foo(col),.groups = "keep")
# with more rows,attributes are NO longer present in tbl2
print(attributes(tbl2$z))
#> NULL

reprex package (v0.3.0) 于 2021 年 4 月 25 日创建

解决方法

谢谢,是的 Akrun 你是对的,列表包装实际上保留了属性!
要完成答案并获得所需的结果(具有属性的非列表列),据我所知,需要一个相当复杂的过程(请参阅代码)。
是否有可能在不中断“管道”流程的情况下实现相同的结果?

suppressWarnings(suppressPackageStartupMessages(library(dplyr)))
suppressWarnings(suppressPackageStartupMessages(library(purrr)))

obj <- c(12,13,51)
attributes(obj)<- list(cv = c(3,4,2))
tbl <- tibble::tibble(col = obj)
print(attributes(tbl$col))
#> $cv
#> [1] 3 4 2

foo <- function(x){
  # to be called within 'summarise()'
  o <- sum(x)
  attributes(o)<- list(cvv = o*2)
  return(o)
}

tbl2 <- tbl %>% 
  group_by(col) %>% 
  summarise(z = list(foo(col)),.groups = "keep")
atts <- map_df(tbl2$z,attributes)
tbl2 <- tbl2 %>% 
  mutate(z = unlist(z))
attributes(tbl2$z)<- atts
# now attributes are present in tbl2!!! but the flow is somewhat twisted!
print(attributes(tbl2$z))
#> $cvv
#> [1]  24  26 102

reprex package (v0.3.0) 于 2021 年 4 月 26 日创建