Сравните 2 кадра данных на равенство в R - PullRequest
0 голосов
/ 12 июня 2019

У меня есть 2 кадра с 2 одинаковыми столбцами. Я хочу проверить, идентичны ли наборы данных. Исходные наборы данных содержат около 700 тыс. Записей, но я пытаюсь найти способ сделать это, используя фиктивные наборы данных

Я пытался использовать сравнение, идентичные, все, all_equal и т. Д. Ни один из них не возвращает мне True.

Фиктивные наборы данных -

a <- data.frame(x = 1:10, b = 20:11)
c <- data.frame(x = 10:1, b = 11:20)

all(a==c)
[1] FALSE

compare(a,c)
FALSE [FALSE, FALSE]

identical(a,c)
[1] FALSE

 all.equal(a,c)
[1] "Component “x”: Mean relative difference: 0.9090909" "Component “b”: Mean relative difference: 0.3225806"

Наборы данных полностью одинаковы, за исключением порядка записей. Если эти функции работают только тогда, когда наборы данных являются зеркальным отображением друг друга, я должен попробовать что-то еще. Если это так, может кто-нибудь помочь с тем, как мне получить True для этих 2 наборов данных (неупорядоченных)

Ответы [ 3 ]

4 голосов
/ 12 июня 2019

dplyr s setdiff работает с фреймами данных, я бы предложил

library(dplyr)
nrow(setdiff(a, c)) == 0 & nrow(setdiff(c, a)) == 0
# [1] TRUE

Обратите внимание, что не учитывает количество повторяющихся строк . (то есть, если a имеет несколько копий строки, а c имеет только одну копию этой строки, он все равно вернет TRUE). Не уверен, как вы хотите обрабатывать дублирующиеся строки ...

Если вам важно иметь одинаковое количество дубликатов, я бы предложил две возможности: (а) добавить столбец идентификаторов для дифференциации дубликатов и использовать описанный выше подход, или (б) сортировку, сброс имен строк ( досадно) и используя identical.

(a) добавление столбца идентификатора

library(dplyr)
a_id = group_by_all(a) %>% mutate(id = row_number())
c_id = group_by_all(c) %>% mutate(id = row_number())
nrow(setdiff(a_id, c_id)) == 0 & nrow(setdiff(c_id, a_id)) == 0
# [1] TRUE

(б) сортировка

a_sort = a[do.call(order, a), ]
row.names(a_sort) = NULL
c_sort = c[do.call(order, c), ]
row.names(c_sort) = NULL
identical(a_sort, c_sort)
# [1] TRUE
1 голос
/ 12 июня 2019

Возможно, вам нужна функция сортировки столбцов перед сравнением. Но это будет медленно на больших фреймах данных.

unordered_equal <- function(X, Y, exact = FALSE){
  X[] <- lapply(X, sort)
  Y[] <- lapply(Y, sort)
  if(exact) identical(X, Y) else all.equal(X, Y)
}

unordered_equal(a, c)
#[1] TRUE
unordered_equal(a, c, TRUE)
#[1] TRUE

a$x <- a$x + .Machine$double.eps
unordered_equal(a, c)
#[1] TRUE
unordered_equal(a, c, TRUE)
#[1] FALSE
0 голосов
/ 12 июня 2019

По сути, вам нужно сравнить упорядоченные базовые матрицы.

all.equal(matrix(unlist(a[order(a[1]), ]), dim(a)),
          matrix(unlist(c[order(c[1]), ]), dim(c)))
# [1] TRUE
identical(matrix(unlist(a[order(a[1]), ]), dim(a)),
          matrix(unlist(c[order(c[1]), ]), dim(c)))
# [1] TRUE

Вы можете заключить это в функцию для большего удобства:

om <- function(d) matrix(unlist(d[order(d[1]), ]), dim(d))

all.equal(om(a), om(c))
# [1] TRUE
...