【问题标题】:Passing lists to sqldf将列表传递给 sqldf
【发布时间】:2017-10-12 21:08:00
【问题描述】:

我有一个数据框列表,我想对其执行合并。如何将列表的每个元素传递给相应的 sqldf 语句? 我的代码如下:

require(sqldf)
a <- data.frame(ID=c("a","b","c","d","a","a"),num=1:6,num2=2:7)
b <- data.frame(ID=c("d","a","a","a","b","c"),num=6:1,num2=7:2)
Datalist <- list(a,b)
mergeto <- data.frame(ID=c("a","a","a","b","c","d"),name=rep("A",6),name2=rep("B"),6)
test <- sqldf("
select *
from Datalist[[1]] as a left outer join mergeto as b
where a.ID = b.ID and
")

我得到错误:

rsqlite_send_query(conn@ptr, statement) 中的错误: 无法识别的令牌:“]”

有没有办法直接从 R 中使用列表变量?我的意思是我知道我可以使用a &lt;- Datalist[[1]],然后在 sqldf 语句中使用a,但是这样每次都创建 Datalist 元素的副本并且 Datalist 已经非常大了..我相信一定有办法.另外要直接访问包含字符串的变量,一定有办法吗? 所以我最终要做的是在循环中执行 SQL 语句,所以我还必须能够更改语句中的索引。但是因为它是一个字符串,它似乎不再那么容易了。

【问题讨论】:

  • 你真的需要使用sqldf吗? in this R-FAQ 很好地涵盖了合并数据框列表。 base::mergedata.table::mergedplyr::left_join 都完全能够进行左连接。
  • 是的,我需要,因为我有一些复杂的合并条件。我认为我不能为此使用基本合并,至少在我大约 1 年前检查时这是不可能的。如果基本合并可以完成 SQL 可以做的所有事情,那么是的,我会立即切换。
  • data.table 可以进行非 equi 连接,但不使用它的 merge 功能 (AFAIK)。我认为使用 SQL df 的最佳选择是 (1) 为列表命名,(2) 使用 list2env 将数据放入环境中,(3) 使用 SQL df 的 envir 参数指定该环境,以及 ( 4)paste 将 sql 语句与您的列表名称放在一起。您可能想用复杂条件的示例提出另一个问题,看看是否可以使用 data.tables 列表及其高级功能。
  • 您能否备份并提供完整的 X 问题而不是您建议的 Y 解决方案(即XY Problem)?您提到了一个循环和复杂的合并条件,但我们在这里都没有看到。
  • 再一次,你没有解释你在做什么。您的重点是包裹。如果您需要合并列表中的多个数据框,请使用chain merge with Reduce()

标签: r sqldf


【解决方案1】:

试试@Gregor 在评论中已经概述的以下内容,但在这里我们明确表示。我们使用 named 列表L 由三个数据帧组成,每个数据帧等于内置的BOD 数据帧,并将第二个和后续数据帧连接到Time 上的第一个数据帧,构造SQL 语句 sql 的文本来自其两部分:sel_from(包含 select 和 from 的字符串)和 joins(连接定义的字符向量)。

library(sqldf)

L <- list(BOD1 = BOD, BOD2 = BOD, BOD3 = BOD) # named list as input
nms <- names(L)
sel_from <- sprintf("select * from %s", nms[1])
joins <- sprintf("join %s on %s.Time = %s.Time", nms[-1], nms[-1], nms[1])
sql <- paste(c(sel_from, joins), collapse = "\n")
sqldf(sql, envir = list2env(L))

这给出了以下输出:

  Time demand Time demand Time demand
1    1    8.3    1    8.3    1    8.3
2    2   10.3    2   10.3    2   10.3
3    3   19.0    3   19.0    3   19.0
4    4   16.0    4   16.0    4   16.0
5    5   15.6    5   15.6    5   15.6
6    7   19.8    7   19.8    7   19.8

我们也可以这样查看sql的内容:

cat(sql, "\n")

给予:

select * from BOD1
join BOD2 on BOD2.Time = BOD1.Time
join BOD3 on BOD3.Time = BOD1.Time 

【讨论】:

  • 酷!现在我需要说更多以使评论足够长..所以..太棒了!我完全在 OP 中做:数据帧列表并针对它们运行 sql。
猜你喜欢
  • 1970-01-01
  • 2014-08-31
  • 2011-11-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多