1

我想将 MySQL 查询从 python 脚本转换为 R 中的类似查询。python 使用循环结构使用基因组坐标搜索特定值:

SQL = """SELECT value FROM %s FORCE INDEX (chrs) FORCE INDEX (sites)
                        WHERE `chrom` = %d AND `site` = %d""" % (Table, Chr, Start)
cur.execute(SQL)

在 R 中,染色体和位点位于数据框中,对于数据框中的每一行,我想提取一个值并将其添加到数据框中的新列中

所以我当前的数据框具有与以下类似的结构:

df <- data.frame("Chr"=c(1,1,3,5,5), "Site"=c(100, 200, 400, 100, 300))

修改后的数据框应该有一个附加列,其中包含来自数据库的值(在相应的基因组坐标处。结构应该类似于:

df <- data.frame("Chr"=c(1,1,3,5,5), "Site"=c(100, 200, 400, 100, 300), "Value"=c(1.5, 0, 5, 60, 100)

到目前为止,我使用以下方式连接到数据库:

con <- dbConnect(MySQL(),
                 user="root", password="",
                 dbname="MyDataBase")

我不想循环遍历数据框中的每一行,而是想使用一些东西来将相应的值添加到现有数据框中的新列中。

根据以下答案更新工作解决方案:

library(RMySQL)
con <- dbConnect(MySQL(),
                 user="root", password="",
                 dbname="MyDataBase")

GetValue <- function(DataFrame, Table){
  queries <- sprintf("SELECT value as value 
                     FROM %s FORCE INDEX (chrs) FORCE INDEX (sites) 
                     WHERE chrom = %d AND site = %d UNION ALL SELECT 'NA' LIMIT 1", Table, DataFrame$Chr, DataFrame$start)
  res <- ldply(queries, function(query) { dbGetQuery(con, query)})
  DataFrame[, Table] <- res$value
  return(DataFrame)
}
df <- GetValue(df, "TableName")
4

4 回答 4

1

我喜欢这种任务的data.table 包,因为它的语法受到 SQL 的启发

require(data.table)

因此,将值与表匹配的示例数据库

table <- data.table(chrom=rep(1:5, each=5), 
                    site=rep(100*1:5, times=5), 
                    Value=runif(5*5))

现在 SQL 查询可以翻译成类似

# select from table, where chrom=Chr and site=Site, value
Chr <- 2
Site <- 200
table[chrom==Chr & site==Site, Value] # returns data.table
table[chrom==Chr & site==Site, ]$Value # returns numeric

用于快速查找的键(索引)数据库(假设唯一的 chrom 和站点..)

setkey(table, chrom, site)
table[J(Chr, Site), ]$Value # very fast lookup due to indexed table

您的数据框作为具有两列“Chr”和“Site”的数据表,均为整数

df <- data.frame("Chr"=c(1,1,3,5,5), "Site"=c(100, 200, 400, 100, 300))
dt <- as.data.table(df) # adds data.table class to data.frame
setkey(dt, Chr, Site) # index for 'by' and for 'J' join

匹配值并附加到新列中(通过引用,因此不复制表)

# loop over keys Chr and Site and find the match in the table
# select the Value column and create a new column that contains this
dt[, Value:=table[chrom==Chr & site==Site]$Value, by=list(Chr, Site)]
# faster:
dt[, Value:=table[J(Chr, Site)]$Value, by=list(Chr, Site)]
# fastest: in one table merge operation assuming the keys are in the same order
table[J(dt)]

亲切的问候

于 2014-06-18T16:11:12.130 回答
1

也许你可以做这样的事情。首先,构建查询,然后执行它们,将结果存储在数据框的列中。不确定 do.call(rbind 部分是否必要,但这基本上需要一堆数据帧行,然后将它们逐行压缩到一个数据帧中。

queries=sprintf("SELECT value as value FROM %s FORCE INDEX (chrs) FORCE INDEX (sites) WHERE chrom = %d AND site = %d UNION ALL SELECT 0 LIMIT 1", "TableName", df$Chrom, df$Pos)
df$Value = do.call("rbind",sapply(queries, function(query) dbSendQuery(mydb, query)))$value

我玩了一点你的 SQL,我对原始 SQL 的关注是它可能返回超过 1 行的情况。

于 2014-08-02T04:49:57.853 回答
0

为什么不使用RMySQLsqldf包?

使用RMySQL,您可以在 R 中访问 MySQL。

使用sqldf,您可以对 R 数据结构发出 SQL 查询。

使用其中任何一个,您都不需要重新编写 SQL 查询来获得相同的结果。

我还要提一下data.table包,它可以让您在使用as.data.table(your.data.frame). 另一个好处是 data.table 对象同时也是一个 data.frame ,因此所有在数据帧上工作的函数也可以在这些转换后的对象上工作。

于 2014-08-03T11:15:37.277 回答
0

您可以轻松使用dplyr包。甚至还有一个很好的小插曲 - http://cran.rstudio.com/web/packages/dplyr/vignettes/databases.html

你需要知道的一件事是:

您可以通过 src_mysql() 连接到 MySQL 和 MariaDB(MySQL 的最新分支),由 RMySQL 包介导。与 PostgreSQL 一样,您需要提供数据库名称、用户名、密码、主机和端口。

于 2014-08-05T14:15:36.317 回答