5

我正在尝试根据多个标准上的两个 data.frames 的交集来填充二进制向量。

我有代码工作,但我觉得只是为了获得二进制向量而内存过多。

当我将代码应用于我的完整数据(40 毫米以上行)时。我开始有记忆问题。

有没有更简单的方法来产生向量?

这是一些样本数据(例如,子样本将仅包括完整样本中的 obs):

ob1_1 <- as.data.frame(cbind(c(1999),c("111","222","666","777")),stringsAsFactors=FALSE)
ob2_1 <- as.data.frame(cbind(c(2000),c("111","333","555","777")),stringsAsFactors=FALSE)
ob3_1 <- as.data.frame(cbind(c(2001),c("111","222","333","777")),stringsAsFactors=FALSE)
ob4_1 <- as.data.frame(cbind(c(2002),c("111","444","555","777")),stringsAsFactors=FALSE)

full_sample <-  rbind(ob1_1,ob2_1,ob3_1,ob4_1)
colnames(full_sample) <- c("yr","ID")

ob1_2 <- as.data.frame(cbind(c(1999),c("111","222","777")),stringsAsFactors=FALSE)
ob2_2 <- as.data.frame(cbind(c(2000),c("333")),stringsAsFactors=FALSE)
ob3_2 <- as.data.frame(cbind(c(2001),c("888")),stringsAsFactors=FALSE)
ob4_2 <- as.data.frame(cbind(c(2002),c("111","444","555","777")),stringsAsFactors=FALSE)

sub_sample <-  rbind(ob1_2,ob2_2,ob3_2,ob4_2)
colnames(sub_sample) <- c("yr","ID")

这是我的工作代码:

q_intersect <- ""
q_intersect <- paste(q_intersect , "select       a.yr, a.ID       ", sep=" ")
q_intersect <- paste(q_intersect , "from         full_sample a  ", sep=" ")
q_intersect <- paste(q_intersect , "intersect                     ", sep=" ")
q_intersect <- paste(q_intersect , "select       b.yr, b.ID       ", sep=" ")
q_intersect <- paste(q_intersect , "from         sub_sample b  ", sep=" ")
q_intersect <- trim(gsub(" {2,}", " ", q_intersect ))

intersect_temp <- cbind(sqldf(q_intersect ),1)
colnames(intersect_temp ) <- c("yr","ID","in_both")

q_expand <- ""
q_expand <- paste(q_expand , "select       in_both            ", sep=" ")
q_expand <- paste(q_expand , "from         full_sample a      ", sep=" ")
q_expand <- paste(q_expand , "left join    intersect_temp  b  ", sep=" ")
q_expand <- paste(q_expand , "on           a.yr=b.yr          ", sep=" ")
q_expand <- paste(q_expand , "and          a.ID=b.ID          ", sep=" ")
q_expand <- trim(gsub(" {2,}", " ", q_expand ))

solution <- as.integer(sqldf(q_expand)[,1])
solution [is.na(solution )] <- 0 

提前感谢您的帮助!

4

2 回答 2

4

目前尚不清楚您要完成什么,但我相信这样的事情会简单得多。

library(data.table)
fullDT <- data.table(full_sample, key=c("yr", "ID"))
subDT  <- data.table(sub_sample,  key=c("yr", "ID"))

fullDT[ , intersect := 0L]
fullDT[subDT, intersect := 1, nomatch=0]

这个想法是你将key每个设置data.table为你想要相交的列。当您致电时,full[sub], nomatch=0]您会获得内部联接,我们仅将这些值设置为1; 内部连接中未标识的值保留为0,如前行中设置的那样。

fullDT
#        yr  ID intersect
#   1: 1999 111         1
#   2: 1999 222         1
#   3: 1999 666         0
#   4: 1999 777         1
#   5: 2000 111         0
#   6: 2000 333         1
#   7: 2000 555         0
#   8: 2000 777         0
#   9: 2001 111         0
#  10: 2001 222         0
#  11: 2001 333         0
#  12: 2001 777         0
#  13: 2002 111         1
#  14: 2002 444         1
#  15: 2002 555         1
#  16: 2002 777         1
于 2013-03-24T05:03:01.470 回答
2

更简单的 SQL 我收集到您希望创建一个具有相同行数的单列数据框,full_sample如果相应行full_sample具有匹配的sub_sample行,则输出中的给定行包含 1,否则为 0。

在这种情况下,可以将多个 SQL 语句压缩为一个更简单的 SQL 语句,如下所示。左连接确保包含所有行,full_sample自然连接导致连接发生在两个输入数据帧之间共有的所有列名上。

sqldf("select s.yr is not null as solution 
       from full_sample f natural left join sub_sample s")

(顺便说一下,请注意,字符串文字可以跨越多行,因此不必将多行粘贴在一起。)

内存不足数据库sqldf 默认使用内存数据库,但您可以通过参数指定文件名(不需要提前存在)dbname=以用作内存不足数据库。在这种情况下,您将不受内存限制。

sqldf("select s.yr is not null as solution 
       from full_sample f natural left join sub_sample s", dbname = "mydb")

(在某些情况下,您还可以通过使用索引来提高性能。有关示例,请参见sqldf 主页。)

更新:添加了更简单的 sql 解决方案

于 2013-03-24T05:31:11.290 回答