【问题标题】:Creating paired combinations from a list of products in a data frame从数据框中的产品列表创建配对组合
【发布时间】:2017-05-23 13:32:36
【问题描述】:

我得到了他们在特定时间段内使用的用户和产品的数据:

dframe <- data.frame(id = c(1234,1234, rep(3456, 4)), 
                     product = c("Apple", "Pear", "Apple", "Pear", "Grapes", "Kiwi"))

  id product
1234   Apple
1234    Pear
3456   Apple
3456    Pear
3456  Grapes
3456    Kiwi

我正在寻找一种方法来为每个用户创建独特的产品对组合(其中 x-y 对等于 y-x 对)。解决方案如下所示:

solution
  id product1 product2
1234    Apple     Pear
3456    Apple     Pear
3456    Apple   Grapes
3456    Apple     Kiwi
3456     Pear   Grapes
3456     Pear     Kiwi
3456   Grapes     Kiwi

基本上,如果有意义的话,我想在 dplyr 的 group_by(id) 之后应用 combn(product,2) 的等效项。有什么想法可以解决这个问题吗?

非常感谢您的帮助!

【问题讨论】:

  • 这是一个错字,现已更正,谢谢!

标签: r dataframe dplyr combinations


【解决方案1】:

这是一个使用来自data.tableCJ 的选项

library(data.table)
setDT(dframe)[, product := as.character(product)
     ][, CJ(product1= product, product2 = product, unique = TRUE), 
  by = id][product1 != product2
  ][!duplicated(data.table(id, pmin(product1, product2), pmax(product1, product2)))]

【讨论】:

  • 嗨@akrun,谢谢你,看起来很有希望,但我从中得到的输出是1234 id的重复对,3456 id只有4个选项......
  • @KasiaKulma 我根据它得到 7 行。
  • 我得到 6 并带有以下警告消息:Warning messages: 1: In Ops.factor(mmm, each) : ‘&gt;’ not meaningful for factors 2: In Ops.factor(mmm, each) : ‘&lt;’ not meaningful for factors 这可以解释差异吗?
  • @KasiaKulma 用product1=as.character(product) 替换product1=productCJ 中的product2 一样,你会得到想要的结果。
  • @KasiaKulma 对不起,我忘了说我把班级改成了character
【解决方案2】:

这是group_by %&gt;% docombn 的选项:

dframe %>% 
    group_by(id) %>% do({
    setNames(
        data.frame(t(combn(.$product, 2)), stringsAsFactors=F), 
    c("product1", "product2"))
})

#Source: local data frame [7 x 3]
#Groups: id [2]

#     id product1 product2
#  <dbl>    <chr>    <chr>
#1  1234    Apple     Pear
#2  3456    Apple     Pear
#3  3456    Apple   Grapes
#4  3456    Apple     Kiwi
#5  3456     Pear   Grapes
#6  3456     Pear     Kiwi
#7  3456   Grapes     Kiwi

【讨论】:

  • 运行您的代码时出现以下错误:Error in names(object) &lt;- nm : 'names' attribute [2] must be the same length as the vector [1],您知道问题出在哪里吗?谢谢!
  • 你有没有在combn前面使用t()来转置结果?
  • 我正确地复制粘贴了你的代码,如果这就是你的要求:)
  • @KasiaKulma 确保您的产品是 as.character
  • 是的。我认为@Sotos 是对的。我忘了说我在构建原始数据框时使用了stringsAsFactors = F
【解决方案3】:

您可以找到一些关于独特组合的功能in this post。如果我们借用@Ferdinand.kraft 在该帖子中定义的函数

expand.grid.unique <- function(x, y, include.equals=FALSE)
{
    x <- unique(x)

    y <- unique(y)

    g <- function(i)
    {
        z <- setdiff(y, x[seq_len(i-include.equals)])

        if(length(z)) cbind(x[i], z, deparse.level=0)
    }

    do.call(rbind, lapply(seq_along(x), g))
}

那我们就可以通过dplyr来使用了,如下,

library(dplyr)

 dframe %>% 
   group_by(id) %>% 
   do(as.data.frame(expand.grid.unique(as.character(.$product), as.character(.$product))))

#Source: local data frame [7 x 3]
#Groups: id [2]

#     id     V1     V2
#  <dbl>  <chr>  <chr>
#1  1245  Apple   Pear
#2  3456  Apple   Pear
#3  3456  Apple Grapes
#4  3456  Apple   Kiwi
#5  3456   Pear Grapes
#6  3456   Pear   Kiwi
#7  3456 Grapes   Kiwi

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-03
    • 2013-07-19
    • 1970-01-01
    • 1970-01-01
    • 2020-04-13
    • 2021-12-10
    相关资源
    最近更新 更多