2013-10-24 1 views
1

Как вы сохраняете факторизованные переменные в левом соединении с использованием sqldf?Сохранение столбца в качестве фактора при выполнении левого соединения с использованием sqldf в R

Я пытаюсь выполнить левое соединение, используя функцию sqldf в R; однако процесс, похоже, преобразует обработанный столбцом в моем «правильном» фрейме данных в класс символов в объединенном наборе данных.

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

Я создал этот воспроизводимый пример:

require(sqldf) 
leftDF <- data.frame(A = sample(1:15, replace = FALSE), 
        B = sample(letters, 15, replace = TRUE), 
        stringsAsFactors = FALSE) 
str(leftDF) 
rightDF <- data.frame(X = sample(1:5, 10, replace = TRUE), 
         Y = sample(letters, 10, replace = TRUE), 
         stringsAsFactors = TRUE) 
str(rightDF) 
mergedDF <- sqldf("SELECT l.A, l.B, r.Y 
        FROM leftDF as l 
        LEFT JOIN rightDF as r 
        ON l.A = r.X") 
str(mergedDF) 

Это ожидаемое поведение sqldf? Преобразование факторируемой переменной в класс символов может быть не очевидным для программистов, пока переменная не будет вести себя так, как они ожидают в будущих анализах.

Я могу сохранить этот фактор, предварительно добавив уровень NA к столбцу с факторизацией до объединения с помощью addNA(); однако, добавление NA как уровня, кажется, не рекомендуется (см. предупреждение в? addNA). Есть ли лучший способ справиться с этим?

Спасибо заранее,

Джефф

Дополнительный пример для рассмотрения комментариев:

require(sqldf) 
leftDF <- data.frame(A = sample(1:15, replace = FALSE), 
        B = sample(letters, 15, replace = TRUE), 
        stringsAsFactors = FALSE) 
str(leftDF) 
rightDF <- data.frame(X = sample(1:5, 10, replace = TRUE), 
         Y = sample(c("one","two","three","four","five","six"), 
           10, replace = TRUE), stringsAsFactors = FALSE) 
rightDF$Y <- factor(rightDF$Y, levels = c("one","two","three","four","five","six")) 
#rightDF$Y <- addNA(rightDF$Y) 
table(rightDF$Y) 
str(rightDF) 
mergedDF <- sqldf("SELECT l.A, l.B, r.Y as Y__factor 
        FROM leftDF as l 
        LEFT JOIN rightDF as r 
        ON l.A = r.X") 
str(mergedDF) 
table(mergedDF$Y, useNA = c("always")) 
+0

на основе быстрого чтения документации я согласен, что это, кажется, противоречит тому, что описано там. Однако я не очень разбираюсь в sqldf. Другая работа, которую я нашел, - это использовать метод 'method = c ('numeric', 'factor', 'factor')'. – joran

ответ

1

Это FAQ #1 на sqldf home page.

В этом случае компоненты mergeDF$Y не входят в число уровней rightDF$Y, следовательно, они не могут использовать уровни последнего и поэтому возвращаются к использованию класса "character".

Можно использовать аргумент method несколькими способами для указания результата. См. ?sqldf.

Альтернативно исправить это, следуя заявлению sqldf.

Вот пример:

# use one of the next two lines or some further variation depending on what you want 
meth <- function(x) replace(x, "Y", factor(x$Y, levels(rightDF$Y))) 
meth <- function(x) replace(x, "Y", factor(x$Y, c(levels(rightDF$Y), NA), exclude=NULL)) 

mergedDF <- sqldf("SELECT l.A, l.B B, r.Y 
        FROM leftDF as l 
        LEFT JOIN rightDF as r 
        ON l.A = r.X", method = meth) ## note use of method=meth 
+0

@ G-Grothendiec, спасибо за ваш вклад. Я нашел FAQ перед публикацией и попробовал метод = «raw», что, как вы могли подозревать, не достигло желаемого результата. Прочитав сообщение, я попробовал 4-й метод, когда я выбрал r.Y как Y__factor. Это работает, при условии, что вам все равно, если отсутствующие уровни будут сброшены и если порядок уровней неважен (например, table (mergeDF $ Y, useNA = c («always»)). Я редактировал свой вопрос с дополнительным примером. В любом случае, чтобы сохранить уровни и порядок уровней с помощью метода «name__class», как описано в аргументе метода? Sqldf? – penguinv22

+0

@ penguinv22, я добавил пример использования 'method' в конце ответа. –