是否可以从.Rdata对象或存储在磁盘上的任何其他大型数据对象中绘制引导样本?我目前从非常大的数据中采样的方法是构建一个本地MySQL数据库,然后使用SQL将随机样本绘制到R中。不幸的是,MySQL中的采样和排序根本没有效率。我想知道是否有人为此用例设计了更好的解决方案。
要了解我当前的解决方案,请参阅MySQL中的采样问题: Simple Random Samples from a Sql database
答案 0 :(得分:5)
您不必将所有数据加载到样本,只需加载行的ID,并从ids中加样。然后仅加载采样行的数据。更详细:
E.g。如果数据库中有一个名为ID
的列,则只加载此列。这应该很快,特别是如果ID
是一个整数。即使你有(比方说)20亿条记录,你只需要8GB内存来存储20亿个整数,所以这应该是可能的。
然后从这些ID中采样。
然后仅加载带有采样ID的记录。
想一想。如果你想从在线书店Siren购买三本随机书籍,你会怎么做? Siren有数百万本书,你不能订购它们,然后在它们之间随机选择,然后发回其余的,对吧?所以你要做的是,你向Siren索取书籍ID列表(ISBN会这样做),这个大小适合于适度的计算机。您可以从列表中随机选择三个,并从Siren中订购这三个。
这显然不适用于.Rdata文件,但.Rdata文件无论如何都是无望的,因为你无法加载一段.Rdata文件。所以你需要一些索引的格式。
但是你可以使用sqlite和RSQLite
包。 RSQLite
支持与数据帧绑定,因此要加载采样数据,只需将采样的id放入名为samp_ids
的数据框(名为id
的单列)中,然后再说
...
my_samp <- dbGetQuery(con, "SELECT * FROM mytable WHERE id = :id",
bind.data = samp_ids)
...
这将读取带有采样ID的记录。
上次我检查RMySQL
时不支持绑定,所以这可能不是可行的方法。如果你坚持使用MySQL,那么我要尝试的第一件事是创建一个临时表,其中只包含采样的行ID,然后将这个表与数据表一起加入。这由RMySQL
支持,它的工作方式如下:
dbSendQuery(con, "CREATE TEMPORARY TABLE tmp (id INTEGER);")
## Stupid, but this seems to be necessary to really create the
## temporary table, it is an RMySQL bug that I reported long time
## ago: https://github.com/jeffreyhorner/RMySQL/issues/10
try(dbSendQuery(con, "CREATE TEMPORARY TABLE tmp (id INTEGER);"))
dbWriteTable(con, "tmp", samp_ids, row.names=FALSE, append=TRUE)
然后,您可以编写SELECT以加入临时表tmp
和原始数据表。