Раствор для данных сообщения в OP
Пример размещены в ОП может быть легко лечится с помощью droplevels()
.
Давайте сначала посмотрим, почему сравнение identical(y[1,], x)
возвращается FALSE
:
str(y[1,])
#'data.frame': 1 obs. of 2 variables:
#$ portfolio_date: Factor w/ 2 levels "2000-10-31","2001-04-30": 1
#$ security : Factor w/ 4 levels "Currency Australia (Fwd)",..: 2
, тогда как
str(x)
#'data.frame': 1 obs. of 2 variables:
#$ portfolio_date: Factor w/ 1 level "2000-10-31": 1
#$ security : Factor w/ 1 level "Currency Euro (Fwd)": 1
Таким образом, разница заключается в факторах, даже если оба объекта отображаются таким же образом, как показано в вопросе ОП.
Здесь полезно использовать функцию droplevels()
: она удаляет неиспользованные факторы. Применяя droplevels()
к y[1,]
с его избыточных факторов, получаем:
identical(droplevels(y[1,]), x)
#[1] TRUE
Если x
также содержит неиспользованные факторы, то это будет необходимо, чтобы обернуть его в droplevels()
тоже. В любом случае, это не будет никакого вреда:
identical(droplevels(y[1,]), droplevels(x))
#[1] TRUE
Общее решение
Использование droplevels()
может не работать, если реальные данные гораздо сложнее, чем данные, размещенные в «MWE "ОП. Такие ситуации могут включать, например, эквивалентные записи в x
и y[1,]
, которые хранятся как разные уровни факторов.Пример, в котором droplevels()
сбой указан в разделе в конце этого ответа.
Следующее решение представляет собой эффективную возможность рассматривать такие общие ситуации. Он работает для данных, размещенных в OP, а также для более сложного случая данных, размещенных ниже.
Сначала создаются два вспомогательных вектора, которые содержат только символы каждой строки. Используя paste()
, мы можем соединить каждую строку в одну строку символов:
temp_x <- apply(x, 1, paste, collapse=",")
temp_y <- apply(y, 1, paste, collapse=",")
С этими векторами, то становится легко можно сравнить строки исходных data.frames, даже если данные были изначально хранились в качестве факторов с различными уровнями и нумерация.
Чтобы определить, какие строки идентичны, мы можем использовать оператор %in%
, который в этом случае более уместен, чем функция identical()
, поскольку первая проверяет равенство всех возможных комбинаций строк, а не только отдельных пар.
С помощью этих простых модификаций требуемого выхода можно получить быстро и без дальнейших циклов:
setNames(temp_y %in% temp_x, names(temp_y))
#10414 10417 10424 21770 21771 21774
# TRUE TRUE FALSE FALSE FALSE FALSE
which(temp_y %in% temp_x)
#[1] 1 2
y[temp_y %in% temp_x,]
# portfolio_date security
#10414 2000-10-31 Currency Euro (Fwd)
#10417 2000-10-31 Currency Euro (Fwd)
данные
x <- structure(list(portfolio_date = structure(1:2, .Label = c("2000-05-15",
"2000-10-31"), class = "factor"), security = structure(c(2L, 1L),
.Label = c("Currency Euro (Fwd)", "Currency USD (Fwd)"),
class = "factor")), .Names = c("portfolio_date", "security"),
class = "data.frame", row.names = c("10234", "10414"))
y <- structure(list(portfolio_date = structure(c(1L, 1L, 1L, 2L, 2L, 2L),
.Label = c("2000-10-31", "2001-04-30"), class = "factor"),
security = structure(c(2L, 2L, 1L, 3L, 2L, 4L),
.Label = c("Currency Australia (Fwd)", "Currency Euro (Fwd)",
"Currency Japan (Fwd)", "Currency United Kingdom (Fwd)"),
class = "factor")), .Names = c("portfolio_date", "security"),
row.names = c(10414L, 10417L, 10424L, 21770L, 21771L, 21774L),
class = "data.frame")
'идентичные (капельки (y [1,]), капли (x))' или, возможно, 'all.equal (y [1,], x, check.attributes = F)' – user20650
Спасибо за попытку, но используя капли в одинаковом состоянии все же возвращают FALSE. Далее, примените (y, 1, function (z) all.equal (z, x, check.attributes = F)) имеет некоторый странный вывод. – lilster
Вам придется преобразовать столбцы в символы. Вот решение в одной строке с базой R: apply (apply (y, 2, as.character), 1, same, apply (x, 2, as.character)) – Dave2e