Dplyr join warning: объединение факторов с разными уровнями

При использовании функции соединения в пакете dplyr я получаю это предупреждение:

Warning message:
In left_join_impl(x, y, by$x, by$y) :
  joining factors with different levels, coercing to character vector

Об этом мало информации в Интернете. Любая идея, что это может быть? Спасибо!

Ответ 1

Это не ошибка, это предупреждение. И это говорит вам, что один из столбцов, которые вы использовали в вашем соединении, был фактором, и этот фактор имел разные уровни в разных наборах данных. Чтобы не потерять какую-либо информацию, факторы были преобразованы в значения символов. Например:

library(dplyr)
x<-data.frame(a=letters[1:7])
y<-data.frame(a=letters[4:10])

class(x$a) 
# [1] "factor"

# NOTE these are different
levels(x$a)
# [1] "a" "b" "c" "d" "e" "f" "g"
levels(y$a)
# [1] "d" "e" "f" "g" "h" "i" "j"

m <- left_join(x,y)
# Joining by: "a"
# Warning message:
# joining factors with different levels, coercing to character vector 

class(m$a)
# [1] "character"

Вы можете убедиться, что оба фактора имеют одинаковые уровни перед слиянием

combined <- sort(union(levels(x$a), levels(y$a)))
n <- left_join(mutate(x, a=factor(a, levels=combined)),
    mutate(y, a=factor(a, levels=combined)))
# Joining by: "a"
class(n$a)
#[1] "factor"

Ответ 2

Это предупреждающее сообщение также появится, если соединительные столбцы в двух таблицах имеют разные порядки уровней;

tb1 <- data_frame(a = c("a","b","c")) %>% mutate(a=as.factor(a))
# Change level order of table tb2 col a
tb2 <- tb1 %>% mutate(a = fct_relevel(a,"c"))

# Check both still factors
tb1$a %>% class()
[1] "factor"
tb2$a %>% class()
[1] "factor"

# Check level order
tb1$a %>% levels()
[1] "a" "b" "c"
tb2$a %>% levels()
[1] "c" "a" "b"

# Try joining
tb1 %>% left_join(tb2)
Joining, by = "a"
Column 'a' joining factors with different levels, coercing to character vector

Ответ 3

В случае базы данных, не забывайте stringsAsFactors=FALSE во многих случаях, чтобы избежать этого предупреждения. (Это был мой случай).

sqlExecute(my_database_channel, data=myparam, stringsAsFactors=FALSE )