У меня есть 2 кадра данных с двумя одинаковыми столбцами. Я хочу проверить, идентичны ли наборы данных. Исходные наборы данных содержат около 700 тыс. записей, но я пытаюсь найти способ сделать это с помощью фиктивных наборов данных.
Я пытался использовать сравнение, идентично, все, все_равно и т. д. Ни один из них не возвращает мне 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 для этих двух наборов данных (неупорядоченных)
Да, я бы не хотел, чтобы x и z были равны. Я просто хочу сравнить кадры данных для одних и тех же записей независимо от их порядка. Что делает lapply sort, так это изменение самих записей набора данных.
dplyr
's setdiff
работает с фреймами данных, я бы посоветовал
library(dplyr)
nrow(setdiff(a, c)) == 0 & nrow(setdiff(c, a)) == 0
# [1] TRUE
Обратите внимание, что это будет не учитывать количество повторяющихся строк. (т. е. если a
имеет несколько копий строки, а c
имеет только одну копию этой строки, он все равно вернет TRUE
). Не уверен, как вы хотите обрабатывать повторяющиеся строки...
Если вам важно иметь одинаковое количество дубликатов, я бы предложил две возможности: (а) добавить столбец идентификаторов, чтобы различать дубликаты и использовать подход, описанный выше, или (б) сортировка, сброс имен строк (раздражает), и используя identical
.
(а) добавление столбца идентификатора
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
Возможно, вам нужна функция сортировки столбцов перед сравнением. Но это будет медленно на больших кадрах данных.
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
lapply(X, sort)
будет сортировать столбцы независимо, что кажется плохим. Учитывая X = data.frame(1:2, 1:2)
, Y = data.frame(2:1, 2:1)
, Z = data.frame(1:2, 2:1)
, я думать OP хотел бы ИСТИНА для X и Y, но ЛОЖЬ для X и Z, но это будет ИСТИНА для всех пар.
Если вы используете do.call(order, X)
и т. д., строки будут упорядочены по всем столбцам.
@Грегор Спасибо, я об этом не подумал. Я задал ОП в комментарии к вопросу, ожидается ли это.
@Грегор, do.call(order, X), похоже, не работает так, как нам хотелось бы. x = data.frame(1:2, 2:1), do.call(order,x) дает объект с 2 значениями, (1,2)
Да do.call(order, x)
задает порядок строк, поэтому на самом деле можно изменить порядок фрейма данных x[do.call(order, x), ]
, как в моем ответе.
В основном вы хотите сравнить упорядоченные базовые матрицы.
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
Вы можете использовать новый пакет под названием waldo
library(waldo)
a <- data.frame(x = 1:10, b = 20:11)
c <- data.frame(x = 10:1, b = 11:20)
compare(a,c)
И вы получаете:
`old$x`: 1 2 3 4 5 6 7 8 9 10 and 9 more...
`new$x`: 10 ...
`old$b`: 20 19 18 17 16 15 14 13 12 11 and 9 more...
`new$b`:
Верен ли этот комментарий пользователя @Gregor? Хотели бы вы, чтобы
X
иZ
были равны нет?