6

大家好,我是 R 新手。

我有两个面板数据文件,列“id”、“date”和“ret”

文件 A 的数据比文件 B 多得多,但我主要处理文件 B 的数据。

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

有没有一种优雅的方式来查找 B 中的每个 (id, date),我需要从文件 A 中获取过去 10 天的 ret,并将它们存储回 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
}

但循环需要永远。

真的很感激你的想法。

非常感谢。

4

7 回答 7

1

我认为关键是矢量化并使用%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)
于 2010-07-12T13:52:25.683 回答
1

你试过吗?合并?

“通过常用列名或行名合并两个数据框,或者做其他版本的数据库连接操作。”

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

于 2010-07-12T08:20:15.913 回答
0

如果您没有在 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)
于 2010-07-12T11:18:58.723 回答
0

这是不是更快?(我假设 B$id 和 B$date 的组合是一个唯一标识符,不会在任何地方复制 - 您的代码暗示)

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)})
于 2010-07-12T04:59:08.243 回答
0

一般来说,您应该避免在 R 中循环。如果您的代码对向量进行操作,它会快得多。

正如ran2 所建议的,我会使用合并。您可以设置all.x = T(或all.yall)从一个(或另一个或两个)数据帧中获取所有行。这很快,通常会自行确定要匹配的字段。否则,您需要将by.x(and by.yor by) 指定为查找字段。根据它的声音,您可能需要自己创建这个字段(根据约翰的评论)。

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

于 2010-07-12T11:48:00.107 回答
0

鉴于您有记忆问题,也许首先削减 A 可能会有所帮助。首先,摆脱无关的ID。

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

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

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

当然,通过不通过 id 来限定它,我们还没有得到 A 的最小版本,但希望它足够小。

现在运行我最初提出的代码,看看是否还有内存错误

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)})
于 2010-07-12T23:17:38.220 回答
0
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 配对。

于 2016-04-06T06:23:46.647 回答