Tidyverse友好的黑客攻击

时间:2018-04-11 21:41:10

标签: r tidyverse

问题很简单,在许多其他帖子中,但我没有找到满意的答案。 假设你有一列标签(这里是字母)和其他列中的其他值(这里只是一个'值')。

data <- tibble(letter = letters[1:5], value = 1:5)

现在你想要的是生成所有没有排列的对,并保持附加到每个对元素的值。这是我所拥有的解决方案,我相信它是有效的但是......不优雅。

combn(data$letter, m = 2) %>%
   t() %>% 
   as_tibble() %>%
   rename(letter_1 = V1, letter_2 = V2) %>% 
   left_join(data, by = c("letter_1" = "letter")) %>% 
   left_join(data, by = c("letter_2" = "letter"), suffix = c("_1", "_2"))

Which outputs the desired result: 
# A tibble: 10 x 4
   letter_1 letter_2 value_1 value_2
   <chr>    <chr>      <int>   <int>
 1 a        b              1       2
 2 a        c              1       3
 3 a        d              1       4
 4 a        e              1       5
 5 b        c              2       3
 6 b        d              2       4
 7 b        e              2       5
 8 c        d              3       4
 9 c        e              3       5
10 d        e              4       5

我真的在寻找一种整齐的方法。我是粉丝男孩:) 提前感谢您的帮助。

3 个答案:

答案 0 :(得分:3)

以下是使用tidyverse(而不是expand)的combn解决方案:

data %>%
    expand(letter_1 = letter, letter_2 = letter) %>%
    mutate(
        value_1 = match(letter_1, letters),
        value_2 = match(letter_2, letters)) %>%
    filter(letter_1 != letter_2) %>%
    rowwise() %>%
        mutate(id = paste0(sort(c(letter_1, letter_2)), collapse = " ")) %>%
    distinct(id, .keep_all = TRUE) %>%
    select(-id)
## A tibble: 15 x 4
#   letter_1 letter_2 value_1 value_2
#   <chr>    <chr>      <int>   <int>
# 2 a        b              1       2
# 3 a        c              1       3
# 4 a        d              1       4
# 5 a        e              1       5
# 7 b        c              2       3
# 8 b        d              2       4
# 9 b        e              2       5
#11 c        d              3       4
#12 c        e              3       5
#13 d        d              4       4
#14 d        e              4       5

答案 1 :(得分:1)

一个选项可能是使用combn

data <- tibble(letter = letters[1:5], value = 1:5)

res <- cbind(data.frame(t(combn(data$letter, 2))), data.frame(t(combn(data$value, 2))))
names(res) <- c("letter_1", "letter_2", "value_1", "value_2")
res
#    letter_1 letter_2 value_1 value_2
# 1         a        b       1       2
# 2         a        c       1       3
# 3         a        d       1       4
# 4         a        e       1       5
# 5         b        c       2       3
# 6         b        d       2       4
# 7         b        e       2       5
# 8         c        d       3       4
# 9         c        e       3       5
# 10        d        e       4       5

答案 2 :(得分:0)

我发现rowwise()函数在我的机器中工作不一致。您可能要尝试使用map()程序中的purrr函数。

这是一种实现方法:

library(purrr)

data %>%
    expand(letter_1 = letter, letter_2 = letter) %>%
    mutate(
        value_1 = match(letter_1, letters),
        value_2 = match(letter_2, letters)) %>%
    filter(letter_1 != letter_2) %>% 
    mutate(
        id = map2_chr(letter_1, letter_2, function(x, y) { 
            paste(sort(c(x, y)), collapse = " ")
        })
    ) %>% 
    distinct(id, .keep_all = TRUE) %>% 
    select(-id)
# # A tibble: 10 x 4
#    letter_1 letter_2 value_1 value_2
#    <chr>    <chr>      <int>   <int>
#  1 a        b              1       2
#  2 a        c              1       3
#  3 a        d              1       4
#  4 a        e              1       5
#  5 b        c              2       3
#  6 b        d              2       4
#  7 b        e              2       5
#  8 c        d              3       4
#  9 c        e              3       5
# 10 d        e              4       5