Как выбрать все уникальные комбинации двух столбцов во фрейме данных R? - PullRequest
1 голос
/ 18 апреля 2019

У меня есть корреляционная матрица, которую я вставил в фрейм данных примерно так:

row | var1 | var2 | cor
1   | A    | B    | 0.6
2   | B    | A    | 0.6
3   | A    | C    | 0.4
4   | C    | A    | 0.4

Эти результаты дублируются в 2 строки каждая, с обеими комбинациями "var1" и "var2".Мне нужен только один, желательно сначала с нижней переменной (например, строки 1 и 3).

Я играю с dplyr в течение двух часов и читаю старые темы, но не могу найти то, что мне нужно.

# get correlation of every concept versus every concept
data.cor <- data.jobs %>% 
  select(-y,-X) %>%
  as.matrix %>%
  cor %>%
  as.data.frame %>%
  rownames_to_column(var = 'var1') %>%
  gather(var2, value, -var1)

Я бы хотел, чтобы вывод выглядел так:

row | var1 | var2 | cor
1   | A    | B    | 0.6
3   | A    | C    | 0.4

Я пытаюсь сделать это, не прибегая к циклу.

Ответы [ 5 ]

2 голосов
/ 18 апреля 2019

Вот один способ с tidyverse -

dat2 <- dat %>% 
  filter(!duplicated(paste0(pmax(var1, var2), pmin(var1, var2))))


# A tibble: 2 x 3
  var1  var2    cor
  <chr> <chr> <dbl>
1 A     B     0.600
2 A     C     0.400

Данные -

dat <- data_frame(
  var1 = LETTERS[c(1,2,1,3)],
  var2 = LETTERS[c(2,1,3,1)],
  cor = c(0.6,0.6,0.4,0.4))

Примечание: очистил логику благодаря @ tmfmnk

1 голос
/ 18 апреля 2019

Решение состоит в том, чтобы заказать var1 и var2 (порядок в алфавитном порядке), а затем использовать уникальные. Я сделал это с помощью data.table для удобства, но это можно сделать с помощью dplyr без проблем.

library(data.table)

dt = data.table(var1 = c("A", "B", "A", "C"), var2 = c("B", "A", "C", "A"), cor = c(0.6 ,0.6, 0.4, 0.4))

dt[, var1_alt := min(var1, var2), by = 1:nrow(dt)]
dt[, var2_alt := max(var1, var2), by = 1:nrow(dt)]

dt = unique(dt[, .(var1 = var1_alt, var2 = var2_alt, cor)])
1 голос
/ 18 апреля 2019

A dplyr Возможны следующие варианты:

df %>%
 group_by(grp = paste0(pmin(var1, var2), pmax(var1, var2))) %>%
 slice(1) %>%
 ungroup() %>%
 select(-grp)

    row var1  var2    cor
  <int> <chr> <chr> <dbl>
1     1 A     B       0.6
2     3 A     C       0.4

Или:

df %>%
 group_by(grp = paste0(pmin(var1, var2), pmax(var1, var2))) %>%
 filter(row_number() == min(row_number())) %>%
 ungroup() %>%
 select(-grp)

Или:

df %>%
 group_by(grp = paste0(pmin(var1, var2), pmax(var1, var2))) %>%
 summarise_all(list(first)) %>%
 ungroup() %>%
 select(-grp)
1 голос
/ 18 апреля 2019

Решение с использованием tidyverse.

library(tidyverse)

dat2 <- dat %>%
  mutate(Var = map2_chr(var1, var2, ~toString(sort(c(.x, .y))))) %>%
  distinct(Var, .keep_all = TRUE) %>%
  select(-Var)
dat2
#   row var1 var2 cor
# 1   1    A    B 0.6
# 2   3    A    C 0.4

DATA

dat <- read.table(text = "row | var1 | var2 | cor
1   | A    | B    | 0.6
2   | B    | A    | 0.6
3   | A    | C    | 0.4
4   | C    | A    | 0.4",
                  sep = "|", stringsAsFactors = FALSE, header = TRUE, strip.white = TRUE)
0 голосов
/ 18 апреля 2019

Вот еще одно tidyverse частичное решение, поскольку я отбросил столбец строки:

library(tidyverse)

data.cor <-
  read.table(
    h = T,
    sep = "|",
    stringsAsFactors = F,
    text = "row | var1 | var2 | cor
            1   | A    | B    | 0.6
            2   | B    | A    | 0.6
            3   | A    | C    | 0.4
            4   | C    | A    | 0.4"
  ) %>%
  mutate_if(is.character, ~ trimws(.))

data.cor
#>   row var1 var2 cor
#> 1   1    A    B 0.6
#> 2   2    B    A 0.6
#> 3   3    A    C 0.4
#> 4   4    C    A 0.4

df <- data.cor %>%
  gather(var, val, var1:var2) %>%
  distinct(cor, val) %>%
  group_by(cor) %>%
  mutate(x = paste("var", 1:n(), sep = "")) %>%
  spread(x, val) %>% 
  ungroup()

df
#> # A tibble: 2 x 3
#>     cor var1  var2 
#>   <dbl> <chr> <chr>
#> 1   0.4 A     C    
#> 2   0.6 A     B

Создано в 2019-04-18 с помощью представьте пакет (v0.2.1)

...