2016-06-03 2 views
1

R хранит факторы как целые числа. Таким образом, при использовании функции одинаковой, она не может найти, когда два фактора имеют одно и то же имя, если они имеют разные уровни.Поведение функции «идентично» с коэффициентами

Вот MWE:

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") 

x <- structure(list(portfolio_date = structure(1L, .Label = "2000-10-31", class = "factor"), 
security = structure(1L, .Label = "Currency Euro (Fwd)", class = "factor")), 
.Names = c("portfolio_date", "security"), row.names = 10414L, class = "data.frame") 

identical(y[1,], x) 

Возвращает FALSE

Но если мы посмотрим на объекты, они оказываются идентичными пользователю

y[1,] 
portfolio_date   security 
10414  2000-10-31 Currency Euro (Fwd) 

x 
portfolio_date   security 
10414  2000-10-31 Currency Euro (Fwd) 

В конце концов, я хочу, чтобы быть в состоянии сделать примерно следующее:

apply(y, 1, identical, x) 
10414 10417 10424 21770 21771 21774 
TRUE TRUE FALSE FALSE FALSE FALSE 
which(apply(y, 1, identical, x)) 
1 2 

Любые предложения относительно того, как достичь этого? Благодарю.

+2

'идентичные (капельки (y [1,]), капли (x))' или, возможно, 'all.equal (y [1,], x, check.attributes = F)' – user20650

+0

Спасибо за попытку, но используя капли в одинаковом состоянии все же возвращают FALSE. Далее, примените (y, 1, function (z) all.equal (z, x, check.attributes = F)) имеет некоторый странный вывод. – lilster

+1

Вам придется преобразовать столбцы в символы. Вот решение в одной строке с базой R: apply (apply (y, 2, as.character), 1, same, apply (x, 2, as.character)) – Dave2e

ответ

1

Для того чтобы выполнить сравнение, факторы необходимо преобразовать в объекты символов. При использовании базового R один здесь представляет собой раствор:

apply(apply(y, 2, as.character), 1, identical, apply(x, 2, as.character)) 

Внутренний применяются циклы преобразования каждого столбца в кадрах данных исходных и целевых объектов для символьных и наружных применяются петли по строкам. Если фрейм данных x имеет более одной строки, фактическое поведение может быть не таким, как ожидалось.

3

Один из вариантов заключается в использовании rowwise от dplyr для проверки строки за строкой; Если вам нужно сравнить row.names одновременно, вам нужно создать столбец id для обоих, в противном случае он вернет TRUE для первых двух строк.

library(dplyr) 
x$id <- row.names(x) 
y$id <- row.names(y) 
rowwise(y) %>% do(check = isTRUE(all.equal(., x, check.attributes = F))) %>% data.frame 

    check 
1 TRUE 
2 FALSE 
3 FALSE 
4 FALSE 
5 FALSE 
6 FALSE 
1

Используйте упаковку «Сравнить».

library(compare) 
result <- NULL 
for (i in 1:NROW(y)){ 
one <- compare(y[i,], x, dropLevels=T) 
two <- one$detailedResult[1]==T & one$detailedResult[2]==T 
result <- c(result, two) 
} 
as.character(result)#TRUE TRUE FALSE FALSE FALSE FALSE 
1

Раствор для данных сообщения в 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") 
Смежные вопросы