使用R中的sqldf执行左连接时保留列作为因子

时间:2013-10-24 17:40:20

标签: r left-join sqldf

如何使用sqldf保留左连接中的因子变量?

我正在尝试使用R中的sqldf函数执行左连接;但是,该过程似乎将我的“正确”数据框中的因子列转换为合并数据集中的字符类。

我怀疑这是因为左连接包含“左”数据帧中的行,“右”数据帧中没有相应的行,因此将NAs引入了因子列。

我创建了这个可重复的例子:

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的预期行为吗?对于程序员来说,将因式变量转换为字符类可能并不明显,直到变量的行为与他们未来的分析方式不同。

我可以通过首先使用addNA()在连接之前向因式列添加NA级别来保留该因子;然而,似乎不鼓励添加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"))

2 个答案:

答案 0 :(得分:1)

这是FAQ #1上的sqldf home page

在这种情况下,mergeDF$Y的组件并非都属于rightDF$Y级别,因此它无法使用后者的级别,因此会恢复使用{{1} } .class。

可以通过多种方式使用"character"参数来指定结果。请参阅method

?sqldf语句之后交替修复它。

以下是一个例子:

sqldf

答案 1 :(得分:0)

使用R中的'sqldf'选择刚刚(并解决)了一个类似的问题。我所有的变量保持不变(因子停留因子,字符停留字符等),但是对于我的一个有序因子变量,成了一个角色变量。

已选中,这是我唯一一个缺少值的变量。所以我把缺失值变成了一个因素,问题解决了,变量在'sqldf'选择后保持不变:-)希望它有所帮助!