【问题标题】:dplyr: Build set of items in list columndplyr:在列表列中构建项目集
【发布时间】:2018-04-11 22:34:07
【问题描述】:

我想要一个基于谓词跟踪集合中包含哪些项目的列。看来我应该能够通过 purrr accumulate 函数和 dplyr lead/lagunion/setdiff 函数的某种组合来做到这一点。

这可能是最好的表达方式:

input_df <- dplyr::data_frame(user = c("1", "1", "1", "1"),
                              item = c("a", "b", "a", "a"),
                              include = c(TRUE, TRUE, FALSE, TRUE))

output_df <- dplyr::data_frame(user = c("1", "1", "1", "1"),
                               set = list(
                                 c("a"),
                                 c("a", "b"),
                                 c("b"),
                                 c("a", "b")))

编辑:我非常接近。我需要找到一种方法来查找向量之间的“包差异”(而不是设置差异),以防用户包含、排除然后重新包含一个项目。

numbered_input_df <- input_df %>% 
  mutate(id = row_number()) 

include_df <- numbered_input_df %>% 
  filter(include == TRUE) %>% 
  mutate(include_set = purrr::accumulate(item, c)) %>% 
  select(user, id, include_set)

exclude_df <- numbered_input_df %>% 
  filter(include == FALSE) %>% 
  mutate(exclude_set = purrr::accumulate(item, c)) %>% 
  select(user, id, exclude_set)

numbered_input_df %>% 
  left_join(include_df) %>% 
  left_join(exclude_df) %>% 
  fill(include_set, exclude_set) %>% 
  mutate(set = map2(include_set, exclude_set, ~.x[! .x %in% .y]))

【问题讨论】:

  • 所以你可以得到像purrr::accumulate(input_df$item, c)这样的简单结果——相当于Reduce(c, input_df$item, accumulate=TRUE)——但是你在include的基础上分组的规则是什么?
  • 抱歉,我不确定我是否理解。我将对用户进行分组,并且对行进行排序,以便下一行直接在前一行之前。
  • 由于这使得输出的每一行都取决于前一行输出,我不确定它是否以矢量化方式可行​​。很高兴被证明是错误的,但您可以编写一个 for() 循环来执行此操作可能会更简单。

标签: r dplyr purrr


【解决方案1】:

定义Update,它将篮子与第 i 个项目的 union 或 setdiff 并使用 Reduce 将其应用于每个 i。使用ave 由用户完成所有操作。没有使用任何包。

Update <- function(basket, i) with(input_df[i, ],
      (if (include) union else setdiff)(basket, item)
)

n <- nrow(input_df)
reduce_user <- function(ix) Reduce(Update, init = NULL, ix, accumulate = TRUE)[-1]

transform(input_df["user"], set = I(ave(as.list(1:n), user, FUN = reduce_user)))

给予:

  user  set
1    1    a
2    1 a, b
3    1    b
4    1 b, a

或者,将上面的代码翻译成 dplyr 和 purrr 并使用上面的Update,我们得到下面的代码。

library(dplyr)
library(purrr)

input_df %>%
  mutate(ix = 1:n()) %>%
  group_by(user) %>%
  mutate(set = accumulate(ix, Update, .init = NULL)[-1]) %>%
  ungroup %>%
  select(user, set)

(请注意,purrr 的唯一用途是 accumulate,如果您想减少依赖关系,可以轻松地将其替换为 Reduce。)

【讨论】:

    猜你喜欢
    • 2021-08-29
    • 2012-05-21
    • 1970-01-01
    • 2010-10-15
    • 2014-12-13
    • 1970-01-01
    • 1970-01-01
    • 2011-10-18
    • 1970-01-01
    相关资源
    最近更新 更多