如何避免环路

如何避免环路

问题描述:

大家好, 我是新来的R.如何避免环路

我有两个面板数据文件,与列“ID”,“日期”和“RET”

文件A有一个比文件B更多的数据, 但我主要使用文件B数据。

“id”和“date”的组合是unqiue唯一标识。

是否有一种在B中查找每个(id,date)的elegent方法,我需要从文件A中取回过去10天,并将它们存储回B?

我做这件事的天真的方法是进行循环您在B中的所有行,

for i in 1:length(B) { 
    B$past10d[i] <- prod(1+A$ret[which(A$id == B$id[i] & A$date > B$date[i]-10 & A$date < B$date[i])])-1 
} 

但环需要永远。

真的很感谢你的想法。

非常感谢。

+1

ķ麻烦:以供将来参考:这是真正有用的人想帮你,如果你的代码问题的文本匹配你问。 – 2010-07-12 15:35:24

+1

sry我的坏。感谢您的帮助 – 2010-07-12 15:49:00

+0

解释它是否符合是开放的。代码只是澄清...按照惯例。 – John 2010-07-12 20:54:46

这是否更快? (我假设B $ ID和B $日期的组合是一个唯一的标识符不会复制任何地方 - 你的代码暗示)

B$idDate <- factor(B$id):factor(B$date) 
B$past10 <- sapply(B$idDate, function(x){with(B[B$idDate == x,], 
    prod(1+A$ret[A$id == id & A$date > date-10 & A$date < date])-1)}) 
+0

感谢您的回复john。它看起来非常整齐。 但当我上的数据,我得到: 错误:无法分配6.8 MB 工作太多大小的向量为B $ past10家伙? – 2010-07-12 13:08:55

+0

这不应该比你的方法更强大的记忆力。尝试用ls()和rm()命令清除内存中的某些内容。或者,尝试重新启动R并再次执行。 – John 2010-07-12 14:59:07

+0

tks!我会尝试..但我忘了提及我的天真方法从来没有完成循环..:S – 2010-07-12 15:35:10

你尝试合并?

“合并由公共列或行名称,两个数据帧或做数据库的其他版本的连接操作。”

此外,我建议如果汽车无使用一点本地的MySQL/PostgreSQL的(RMySQL/RPostgreSQL)数据库运动复合PK或任何唯一标识符。对我来说,SQL重新排列数据和事后使用视图中的data.frames比循环要容易得多。

+0

嗯..我可能需要看看sql。 谢谢! – 2010-07-12 13:09:35

+0

RMySQL更容易开始...... – 2010-07-12 13:25:33

如果您还没有在A和B中复制的数据,那么rbind是最简单的解决方案。

#Sample data 
A <- data.frame(
    id = rep(letters[1:3], each = 13), 
    date = Sys.Date() + -12:0, 
    ret = runif(39) 
) 

B <- data.frame(
    id = rep(letters[5:6], each = 5), 
    date = Sys.Date() + -4:0, 
    ret = runif(10) 
) 

#Only take the last ten days from A 
A_past_10_days <- A[A$date > Sys.Date() - 10,] 

#Bind by rows 
rbind(A_past_10_days, B) 
+0

从现在开始,您已经过去了10天,但是他的代码需要在每个可能日期的过去10天内使用符合该日期的标识符进行限定。 – John 2010-07-12 14:52:35

+0

@John:斑点。我似乎已经回答了问题的文本,但不是隐藏在代码中的问题。 **叹息** – 2010-07-12 15:32:56

一般而言,您应该避免在R中循环。如果您的代码在向量上运行,则速度会更快。

我会使用合并,由ran2建议。您可以设置all.x = T(或all.yall)以从一个(或其他或两个)数据框中获取所有行。这很快,通常会解决哪些字段需要自行匹配。否则,您需要指定by.x(和by.yby)作为查找字段。通过它的声音,你可能需要自己创建这个领域(按照约翰的评论)。

然后,您可以按日期过滤。

+0

tks! B实际上是A的一个小得多的子集,所以如果我理解'合并'正确,那么A将是合并的结果。 – 2010-07-12 13:11:37

+0

这将占用比原来的解决方案更多的内存。鉴于你的记忆力限制与我的建议,这将不太可能奏效。此外,所有这一切都是让你的数据到一个地方。它并不能解决你将过去10天变成单一价值的问题......你的代码建议这是必要的。 – John 2010-07-12 21:03:51

+0

啊!我的错。我以为你得到了一组从A到B的行。我没有意识到你真的想要总结产品。您也可能对聚合(sapply的便利功能)感兴趣。如果你有内存问题,那么你可能需要一个小样本,你可以练习,直到你确信代码有效(另见:http://www.r-bloggers.com/memory-management -in-RA-几个小窍门,和技巧/)。 – RobinGower 2010-07-13 08:52:33

我认为关键是矢量化和使用%in%算子子集数据框A。而且,我知道,价格不是随机数,但我不想随机散步......我使用paste创建了股票日期指数,但我相信您可以使用pdata.frame中的指数plm图书馆,这是我发现的面板数据最好的。

A <- data.frame(stock=rep(1:10, each=100), date=rep(Sys.Date()-99:0, 10), price=rnorm(1000)) 
B <- A[seq(from=100, to=1000, by=100), ] 
A <- cbind(paste(A$stock, A$date, sep="-"), A) 
B <- cbind(paste(B$stock, B$date, sep="-"), B) 
colnames(A) <- colnames(B) <- c("index", "stock", "date", "price") 
index <- which(A[, 1] %in% B[, 1]) 
returns <- (A$price[index] - A$price[index-10])/A$price[index-10] 
B <- cbind(B, returns) 

鉴于您有内存问题,也许削减第一个可能会帮助。首先,摆脱外来的艾滋病。

A <- A[A$id %in% B$id,] 

完全减少A数据集仍然想要获取更多内存。没有存储一些变量是不可能的。尽管如此,我们可以通过削减每一个日期低于绝对最小值并高于绝对最大值的方式来摆脱它所希望的一堆。

A <- A[A$date > (min(B$date) - 10) & A$date <= max(B$date),] 

当然,通过不受ID排位这一点,我们没有得到一个可能的最小的版本,但希望它足够小。

现在来看,我首先提出的代码,看看您是否仍然有一个内存错误

B$idDate <- factor(B$id):factor(B$date) 
B$past10 <- sapply(B$idDate, function(x){with(B[B$idDate == x,], 
    prod(1+A$ret[A$id == id & A$date > date-10 & A$date < date])-1)}) 
+0

谢谢约翰,这两行帮助在A中减少很多,但是在我尝试了500行之后,它仍然给了我错误:无法分配6.8 Mb大小的向量。我认为问题可能在'安乐死'。不知何故,它将id和date数据作为向量并试图比较A $ id和B $ id等,而不是元素 – 2010-07-13 13:47:43

+0

看起来像是sapply(B $ idDate),这就是创建问题,我将B $ idDate更改为字符和代码一直在运行........闻起来像一个循环 – 2010-07-13 17:09:42

+0

尽量不要把过去10放在B中(在第二行开始时删除B $)。这是否也有记忆问题? sapply()将B的每个元素都取出来,然后使用它来重新选择A并得到产品......就像在原始代码中那样。我演示了我的代码,但在我的电脑上6.8meg是一个微不足道的内存(我只用了大约200行)。如果它报告了错误消息,那么确切的消息是什么? – John 2010-07-13 17:10:55

library(data.table) 
#create data 
A <- data.table(id=rep(1:10, each=40000), date=rep(Sys.Date()-99:0, 4000), ret=rnorm(400000)) 
B <- data.table(id=rep(1:5, each=10), date=rep(Sys.Date()-99:0), ret=rnorm(50)) 

#find dates to compare against 
n <- NROW(B) 
B_long <- B[,.(id = rep(id,each=10),date = rep(date,each=10))] 
s <- rep(-10:-1,n) 
B_long[,date:=date + s] 

#information in one column 
B_long$com <- as.numeric(paste0(B_long$id,as.numeric(B$date))) 
A$com <- as.numeric(paste0(A$id,as.numeric(A$date))) 

#compare 
setkey(A,com) 
X <- A[com %in% B_long$com,] 

这个答案建立在理查兹的答案,但更有针对性的问题。

主要想法是构建一个id日期组合向量进行比较。这发生在第二个代码块中。

我的解决方案使用data.table包,但应该在语法更改时使用data.frame。但是使用data.table包具有keycolumns的优点。

如果你仍然有可以配对,这种方法与约翰的第二个答案,第一批A.