【问题标题】:Preserving a column as a factor when performing a left join using sqldf in R在 R 中使用 sqldf 执行左连接时将列保留为一个因素
【发布时间】:2018-04-24 05:02:31
【问题描述】:

如何使用 sqldf 在左连接中保留因式变量?

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

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

我创建了这个可重现的示例:

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 中的警告)。有没有更好的处理方法?

提前致谢,

杰夫

解决 cmets 的另一个示例:

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

【问题讨论】:

  • 基于对文档的快速阅读,我同意这似乎与那里的描述相反。不过,我对 sqldf 不是很有经验。我发现的另一个解决方法是使用method = c('numeric','factor','factor')

标签: r left-join sqldf


【解决方案1】:

这是sqldf home page 上的FAQ #1

在这种情况下,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

【讨论】:

  • @G-Grothendiec,感谢您的意见。在发布之前我确实找到了常见问题解答并尝试了 method = "raw",您可能会怀疑它没有达到预期的结果。阅读您的帖子后,我尝试了选择 r.Y 作为 Y__factor 的第 4 种方法。如果您不在乎丢失的级别是否被删除并且级别的顺序是否不重要(例如,table(mergeDF $ Y,useNA = c(“always”)),则此方法有效。我已经用一个附加示例编辑了我的问题。如 ?sqldf 的方法参数中所述,是否有任何方法可以使用“name__class”方法保留级别和级别顺序?
  • @penguinv22,我在答案末尾添加了一个使用method的示例。
【解决方案2】:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-11-19
    • 2015-11-11
    • 2015-07-28
    • 1970-01-01
    • 2021-12-19
    • 2023-02-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多