【问题标题】:dplyr grouped cumulative set counting using group_by and rowwise dodplyr 使用 group_by 和 rowwise 进行分组累积集计数
【发布时间】:2017-02-14 10:21:48
【问题描述】:

我已经在每行包含一个值列表的组内按顺序对数据进行分组,并且在每个组内,我想生成每行贡献给每个组中列表联合的新列表值的计数。

这是一个例子:

require(dplyr)
content <- list(c("A", "B"), c("A", "B", "C"), c("D", "E"), c("A", "B"), c("A", "B"), c("A", "B", "C"))
id <- c("a", "a", "a", "b", "b", "b")
order <- c(5, 7, 3, 1, 9, 4)
testdf <- data.frame(id, order, cbind(content))
testdf
#   id order content
# 1  a     5    A, B
# 2  a     7 A, B, C
# 3  a     3    D, E
# 4  b     1    A, B
# 5  b     9    A, B
# 6  b     4 A, B, C

我想要的输出(按每个组内的降序排序后)如下:

#   id order content cc
# 1  a     7 A, B, C 3
# 2  a     5    A, B 3
# 3  a     3    D, E 5
# 4  b     9    A, B 2
# 5  b     4 A, B, C 3
# 6  b     1    A, B 3

cn (累积新)确实比 cc (累积计数)更可取,但上面映射到我下面的尝试,随后很容易计算出 cn。这是我尝试的不起作用的解决方案:

res <- testdf %>% 
  arrange(id, desc(order)) %>% 
  mutate(n=row_number()) %>%
  group_by(id) %>%
  mutate(n1=first(n)) %>%
  rowwise() %>%
  bind_cols(do(.,data.frame(vars=length(unique(unlist(testdf$content[.$n1:.$n])))))) %>%
  data.frame

我实际上从这里获得了大部分解决方案:Cumulatively paste (concatenate) values grouped by another variable(感谢 akrun)。生成的值似乎是正确的,但它们与源数据框中的正确行没有关联:

res
#   id order content n n1 vars
# 1  a     7 A, B, C 1  1    2
# 2  a     5    A, B 2  1    3
# 3  a     3    D, E 3  1    5
# 4  b     9    A, B 4  4    2
# 5  b     4 A, B, C 5  4    2
# 6  b     1    A, B 6  4    3

如您所见(查看与上面的 cc 等效的 vars 列),“a”组的值 2 和 3 颠倒了,而“b”组的第二个值 2 和 3 颠倒了。

实际上我找出了上面的问题,testdf$content(显然)与 dplyr'd 数据框的排序不同。最初我有.$content 而不是testdf$content 并且产生了更奇怪的输出。所以我尝试分两个阶段进行:

res <- testdf %>% 
    arrange(id, desc(order)) %>% 
    mutate(n=row_number()) %>%
    group_by(id) %>%
    mutate(n1=first(n))
res <- res %>% 
    rowwise() %>%
    bind_cols(do(.,data.frame(vars=length(unique(unlist(res$content[.$n1:.$n])))))) %>%
    data.frame

这会产生我所期望的:

#   id order content n n1 vars
# 1  a     7 A, B, C 1  1    3
# 2  a     5    A, B 2  1    3
# 3  a     3    D, E 3  1    5
# 4  b     9    A, B 4  4    2
# 5  b     4 A, B, C 5  4    3
# 6  b     1    A, B 6  4    3

所以我现在的问题是有没有更好的方法来引用 do() 内的整个 dplyr 修改的数据框(以便正确排序 content) - 我认为 . 只是当前行不是吗?能够这样做将避免我必须在 do() 之前单独创建有序数据框。

非常感谢

提姆

【问题讨论】:

  • 我对所有步骤都感到有些困惑,但假设您已经对数据进行了适当的排序和分组,您可以使用cumsum(!duplicated(unlist(x)))[cumsum(lengths(x))] 进行累积计数,其中x 是有序的“内容” ——例如list(c("A", "B", "C"), c("A", "B"), c("D", "E")) 用于“a”组中的有序“内容”,list(c("A", "B"), c("A", "B", "C"), c("A", "B")) 用于“b”组中。
  • 感谢您的回复 - 我很快就开始了,但我不确定在哪里尝试,是否应该替换整个 rowwise()bind_cols(do())?我天真地尝试了res %&gt;% cumsum(!duplicated(unlist(content)))[cumsum(lengths(content))],它给了NA?
  • 按照您的代码,我想到了 testdf %&gt;% arrange(id, desc(order)) %&gt;% group_by(id) %&gt;% mutate(cumsum(!duplicated(unlist(content)))[cumsum(lengths(content))]) 之类的东西
  • 好的,谢谢 - 虽然我不太确定使用 cumsum(lengths(content)) 从列表中进行选择是如何工作的。我认为@Psidom 的解决方案可能更容易理解,所以我会接受它作为解决方案。再次感谢您的贡献。
  • 顺便说一句 - 我喜欢你为此目的使用带有“累积”命名的方法,尽管双重使用有点令人困惑。

标签: r dplyr


【解决方案1】:

您可以使用Reduce 函数和accumulate 模式来创建累积不同的元素,然后使用lengths 函数返回累积的不同计数,这样可以避免rowwise() 操作:

library(dplyr)
testdf %>% 
          arrange(desc(order)) %>% 
          group_by(id) %>% 
          mutate(cc = lengths(Reduce(function(x, y) unique(c(x, y)), content, acc = T))) %>% 
          arrange(id)

#Source: local data frame [6 x 4]
#Groups: id [2]

#      id order   content    cc
#  <fctr> <dbl>    <list> <int>
#1      a     7 <chr [3]>     3
#2      a     5 <chr [2]>     3
#3      a     3 <chr [2]>     5
#4      b     9 <chr [2]>     2
#5      b     4 <chr [3]>     3
#6      b     1 <chr [2]>     3

【讨论】:

  • 谢谢,这是一个很好的解决方案!对于何时需要按行与能够使用矢量化解决方案,是否有经验法则?
  • 我不确定是否有,但要避免在可以矢量化时使用行操作,这将是我的经验法则,因为行操作通常很昂贵。
  • 请问上面第一个arrange和group_by的顺序是否重要。有人可能认为 group_by 之后的安排会在组内安排,但我不确定这是否按预期工作?谢谢。
  • 据我所知,group_byarrange 的顺序应该不会影响。我找不到对此的有力支持。但是您可能会发现这很有用:blog.rstudio.org/2016/06/27/dplyr-0-5-0
  • 啊,是的,很有趣,所以它曾经有所作为,但现在不是因为安排忽略了 0.5.0 之后的分组,也许我已经看到了一些旧帖子。谢谢。
猜你喜欢
  • 2020-10-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-19
  • 1970-01-01
  • 2018-04-05
  • 2020-08-07
  • 2015-07-31
相关资源
最近更新 更多