【发布时间】:2020-08-15 12:03:04
【问题描述】:
我有两个数据框:Sales 和 Clients。我想使用sqldf::sqldf() 和merge() 对这些数据帧执行交叉连接,并使用这两种方法获得完全相同的结果。
到目前为止,我只能获得两个数据帧,其中行的顺序不同。
这是生成Sales 和Clients 数据帧的代码:
set.seed(1)
Sales <- data.frame(
Product = sample(c("Toaster", "Radio", "TV"), size = 7, replace = TRUE),
CustomerID = c(rep("1_2019", 2), paste(2:3, "2019", sep = "_"), paste(1:3, "2020", sep = "_"))
)
Sales$Price <- round(ifelse(Sales$Product == "TV", rnorm(1, 400, 20),
ifelse(Sales$Product == "Toaster", rnorm(1, 40, 2),
rnorm(1, 35, 2))))
Clients <- data.frame(
CustomerID = c(paste(2:4, "2019", sep = "_"), paste(1:2, "2020", sep = "_")),
State = sample(c("CA", "AZ", "IL", "MA"), size = 5, replace = TRUE)
)
这是我得到的:
library(sqldf)
# cross join with base R
out1 <- merge(x = Sales, y = Clients, by = NULL)
# cross join with sqldf
out2 <- sqldf("SELECT *
FROM Sales
CROSS JOIN Clients")
out1 和 out2 具有不同的行顺序。如何调整sqldf() 调用以使out1 和out2 完全相同?
这是我得到的最接近的:
merge(x = Sales, y = Clients, by = NULL)
sqldf("SELECT *
FROM Sales
CROSS JOIN Clients
ORDER BY State DESC, Clients.CustomerID")
【问题讨论】:
-
使用
out1 <- merge(...)和out2 <- sqldf(...),然后dplyr::arrange(out1, desc(State), CustomerID.y)使两者相同(列名除外)。这实际上只是将您的 sqlorder by转换为dplyr。我没有尝试过基本的 R 等价物,因为你想减少一个而不是另一个...... -
@r2evans 感谢您的评论。实际上我不想要任何特定变量排序的结果,我只想获得两个相等的数据帧。
sqldf()中的order by子句和select子句之后的变量只是我试图复制使用merge()获得的默认排序,但到目前为止我还没有成功。 -
@r2evans 我编辑了问题以包含更多信息,以便更容易理解我想要完成的工作。
-
处理 SQL 数据库时的一件事(您可能已经知道这一点):您不能相信数据在 中返回的顺序,除非您使用“order by”明确设置它 ”。它可能会也可能不会尊重进入其中的数据的顺序。现在这是一般的 SQL,也许 SQLite 尊重自然(导入)顺序,我不知道。但听起来你试图让
sqldf模仿merge输出的顺序,对吗?嗯。这听起来像是一种学术追求,到底是什么原因导致了这个兔子洞? -
@r2evans 是的,这就是我想要做的。我有一些使用
merge连接所有表格的讲座幻灯片,我试图将这些连接中的每一个与sqldf中的等效连接并行。我课程的重点是 R,而不是 SQL,但我决定包含一些 SQL 示例(使用sqldf),这样我的学生在工作时就不会看到他们的第一个 SQL 代码(就像几年前发生在我身上一样) )。我过去使用过 SQL,但主要是通过 R 和(在我以前的工作中)SAS,但自从我学习了 dplyr,我就停止使用sqldf。