#r #dplyr #tidyr
#r #dplyr #tidyr
Вопрос:
У меня есть корреляционная матрица, которую я помещаю в фрейм данных следующим образом:
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
Я пытаюсь сделать это, не прибегая к циклу.
Ответ №1:
Вот один из способов с 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 логика была очищена
Ответ №2:
Решение с использованием 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
ДАННЫЕ
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)
Ответ №3:
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)
Ответ №4:
Решение состоит в том, чтобы упорядочить var1 и var2 (порядок в алфавитном порядке), а затем использовать unique . Я сделал это с помощью 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)])
Ответ №5:
Вот еще одно tidyverse
частичное решение, поскольку я удалил столбец row:
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 пакетом reprex (версия 0.2.1)