【问题标题】:Put the combinations matrix of many rows in a column of a dataframe, then split it将多行的组合矩阵放在数据框的一列中,然后将其拆分
【发布时间】:2017-05-25 16:28:20
【问题描述】:

我有一个看起来像这样的数据框(我简化了):

df <- data.frame(rbind(c(1, "dog", "cat", "rabbit"), c(2, "apple", "peach", "cucumber")))
colnames(df) <- c("ID", "V1", "V2", "V3")

##   ID    V1    V2       V3
## 1  1   dog   cat   rabbit
## 2  2 apple peach cucumber

我想创建一个列,其中包含变量 V1:V3 的所有可能组合,两个两个(顺序无关紧要),但保持与原始 ID 的链接。所以像这样。

##    ID  bigrams
## 1   1    dog cat
## 2   1    cat rabbit
## 3   1    dog rabbit
## 4   2    apple peach
## 5   2    apple cucumber
## 6   2    peach cucumber

我的想法:使用combn()mutate()separate_row()

library(tidyr)
library(dplyr)

df %>% 
mutate(bigrams=paste(unlist(t(combn(df[,2:4],2))), collapse="-")) %>% 
separate_rows(bigrams, sep="-") %>% 
select(ID,bigrams)

结果不是我所期望的……我想连接一个矩阵(combine() 的结果)没有那么容易。

对此我有两个问题:1)如何调试这段代码? 2)这是做这种事情的好方法吗?我是 R 新手,但我有 Open Refine 背景,所以连接拆分多值单元格对我来说很有意义。但这也是 R 的正确方法吗?

提前感谢您的帮助。

【问题讨论】:

    标签: r dplyr tidyr


    【解决方案1】:

    我们可以通过data.table 做到这一点。将'data.frame'转成'data.table'(setDT(df)),melt转成'long'格式,按'ID'分组,得到'value'的combnpaste一起

    library(data.table)
    dM <- melt(setDT(df), id.var = "ID")[, combn(value, 2, FUN = paste, collapse=' '), ID]
    setnames(dM, 2, 'bigrams')[]
    #   ID        bigrams
    #1:  1        dog cat
    #2:  1     dog rabbit
    #3:  1     cat rabbit
    #4:  2    apple peach
    #5:  2 apple cucumber
    #6:  2 peach cucumber
    

    【讨论】:

    • 哇! 0_0 我知道 data.table 是一个强大的包,但它对我来说似乎总是很复杂,特别是专门用于大数据帧。我将尝试学习它以理解这两行。非常感谢,@Akrun!我会等一下,但我不知道如何使它更短。
    • tidyverse 中的翻译是:df %&gt;% gather("variable", "value", -ID) %&gt;% group_by(ID) %&gt;% transmute(bigrams = combn(value, 2, paste, collapse = " ")) %&gt;% ungroup()。这里没有附加值,所以我不会单独回答
    • 谢谢,Aurèle!现在,我对 tidyverse 感觉更舒服。
    【解决方案2】:

    我推荐@akrun 的“melt first”方法,但只是为了好玩,这里有更多方法:

    library(tidyverse)
    df %>% 
      mutate_all(as.character) %>% 
      transmute(ID = ID, bigrams = pmap(
        list(V1, V2, V3), 
        function(a, b, c) combn(c(a, b, c), 2, paste, collapse = " ")
      ))
    #   ID                                     bigrams
    # 1  1             dog cat, dog rabbit, cat rabbit
    # 2  2 apple peach, apple cucumber, peach cucumber
    

    mutate_all(as.character) 只是因为你给了我们因素,而因素到字符的转换可能会令人惊讶)。

    df %>% 
      mutate_all(as.character) %>%
      nest(-ID) %>% 
      mutate(bigrams = map(data, combn, 2, paste, collapse = " ")) %>%
      unnest(data) %>% 
      as.data.frame()
    #   ID                                     bigrams    V1    V2       V3
    # 1  1             dog cat, dog rabbit, cat rabbit   dog   cat   rabbit
    # 2  2 apple peach, apple cucumber, peach cucumber apple peach cucumber
    

    as.data.frame() 只是为了更漂亮的打印)

    【讨论】:

    • 非常有趣的解决方案,这无疑会在其他情况下保留我。我将详细检查它。既然我已经看到了data.table 和`tidyverse` 中的解决方案,我将按照您的建议选择第一个答案,它更快更短。非常感谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-03-15
    • 2021-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-06
    相关资源
    最近更新 更多