gpt4 book ai didi

R:更快地合并数据帧

转载 作者:行者123 更新时间:2023-12-02 07:21:57 28 4
gpt4 key购买 nike

我刚刚开始使用 R 并编写了以下代码,但这需要大约 40 分钟来处理,所以我确信可以以运行速度更快的方式对其进行编码。

基本上,我有一个大约 7GB n 大小的大数据集 ( crsp_td_net ) 和第二个较小的数据集 ( ff_35f )。两者都包含交易日期。我想要做的是在第一个数据集中填写每个公司的交易日期。

从我的第一个数据集,我根据公司索引创建数据子集,然后根据交易日期将每个子集与第二个数据集合并。这个合并的数据集被附加到其他公司的数据集,依此类推,直到最后,我留下了一个包含所有初始公司的大数据集,但包含了缺失的交易日。

我现在不确定数据框 final 是否是事实。不断扩展导致我的循环运行缓慢或循环本身是否编码效率低下。我知道数据的矢量化可以帮助加快速度,但我不确定如何在此处执行此操作(每个公司的数据子集的矩阵大小不断变化)。我也不确定使用 apply 的最佳方式, sapplylapply (如果其中任何一个可以在这里使用)为此。我浏览了一些关于 R 的查询,但我还没有找到解决这个问题的方法。我非常感谢可以使下面的运行速度更快的替代代码片段。

todo<-matrix(numeric(0), 0,4)

for (i in 1:7396) {
final<- crsp_td_net %>%
filter(compid==i) %>%
merge(ff_35f,by="date_crsp",all=TRUE)

final<-final%>% filter(between(date_crsp,
as.Date(min(date_crsp_orig,na.rm="TRUE")),
as.Date(max(date_crsp_orig, na.rm="TRUE")))) %>%
arrange(date_crsp) %>%
mutate(cusip8dg_compustat =
ifelse(is.na(cusip8dg_compustat),
max(cusip8dg_compustat, na.rm="TRUE"),
cusip8dg_compustat)) %>%
mutate(compid = ifelse(is.na(compid), i, compid))%>%
select(compid, cusip8dg_compustat, date_crsp,
date_crsp_orig)%>%
distinct()

todo<-bind_rows(todo,final)
}

提前致谢,

开发

谢谢大家的回复。由于回复限制,我无法在评论框中回复,所以我添加到我的原始帖子中。 @P Lapointe,请找到一个可重现的数据集(我使用的是整数值而不是实际日期)@eipi10 - 我想你已经理解我的意思并感谢代码,但我不确定它是否缺少某些东西正在提示输入(我有所有相关的库)。 @Alistaire - 当我执行更多计算以添加到原始数据集时,我确实会面临内存问题。感谢您提供有关如何使循环更快/替代它的建议,这对于理解它们将如何在下面的示例中实现非常有帮助。

非常感谢
zz <- "compid  date_crsp 
1 1 2
2 1 3
3 1 5
4 2 3
5 2 7
6 2 9
7 3 3
8 3 5
9 3 7
10 3 8"
crsp_td_net <- read.table(text=zz, header = TRUE)


xx <- "date_crsp
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9
10 10
11 11"

ff_35f <- read.table(text=xx, header = TRUE)

# I expect my final output to look like this:

yy<-"compid date_crsp
1 1 2
2 1 3
3 1 4
4 1 5
5 2 3
6 2 4
7 2 5
8 2 6
9 2 7
10 2 8
11 2 9
12 3 3
13 3 4
14 3 5
15 3 6
16 3 7
17 3 8"

output_wanted<-read.table(text=yy, header = TRUE)

df <- full_join(crsp_td_net, expand.grid(compid = unique(crsp_td_net$compid), date_crsp=unique(ff_35f$date_crsp)))

todo<-array(numeric(),c(1,4,0))
todo<-matrix(numeric(0), 0,0)



for (i in 1:3) {

final<- filter(crsp_td_net,compid==i)
final<- mutate(final,date_crsp_orig=date_crsp)
final<- merge(final,ff_35f, by="date_crsp",all=TRUE)
final<- filter(final,between(date_crsp, min(date_crsp_orig, na.rm=TRUE), max(date_crsp_orig, na.rm=TRUE)))
final<- arrange(final,date_crsp)
final<- mutate(final,compid = ifelse(is.na(compid), i, compid))
final<- select(final,compid, date_crsp)
final<- distinct(final)
todo<-bind_rows(todo,final)
}

我已经修改了 full_join 示例,它现在运行,但没有做我想要它做的事情,重新合并每个 compid 与唯一的交易日以填补第一个数据集中缺少的交易日。我非常感谢您对此提出任何建议。

我上面写的循环可以准确地给我我想要的东西,但我想知道是否有更快的方法来做到这一点,因为我将不得不循环超过 7000 个 compid 来创建大数据集 todo。这大约需要 40 分钟才能运行,所以我想知道是否有更快的方法来编写这个循环或替代它。

提前谢谢了
crsp_td_net$date_crsp_orig <-crsp_td_net$date_crsp

df <- full_join(crsp_td_net, by="date_crsp", expand.grid(compid = unique(crsp_td_net$compid), date_crsp=unique(ff_35f$date_crsp)) )
df<- df%>% filter(between(date_crsp, min(date_crsp_orig, na.rm=TRUE), max(date_crsp_orig, na.rm=TRUE)))
df<- df%>%filter(!compid.x=="NA")%>% select(-compid.y)%>% distinct()%>%arrange(compid.x,date_crsp)

最佳答案

尽管 OP 要求提供 dplyr解决方案,我只能建议使用 foverlaps() 的解决方案来自 data.table 的函数包裹。

OP 已要求在 crsp_td_net 中完成每家公司的交易日期。按 ff_35f 中给出的交易日期.完成意味着用给定的日期填充从开始日期到结束日期的日期范围。 (请注意,OP 使用整数值代替日期)。给定的日期也可以被视为日期范围,其中每个范围仅包含一天。

现在,问题已被解释为找到(日期)范围(重叠连接)的两个序列的重叠。为此,foverlaps()可以使用受 findOverlaps() 启发的函数Bioconductor's IRanges package 的功能但也适用于非基因组(即非整数)范围。

library(data.table)
# coerce to data.table
setDT(crsp_td_net)
setDT(ff_35f)

# find start and end date for each company
comp_date_range <- crsp_td_net[, .(start = min(date_crsp), end = max(date_crsp)),
by = compid]

# turn given dates into date ranges of one day lengths
# by adding an end column equal to the start dates
ff_35f[, end := date_crsp]

# set keys
setkey(comp_date_range, start, end)
setkey(ff_35f, date_crsp, end)

# find all overlapping ranges
temp <- foverlaps(comp_date_range, ff_35f)

# reorder result for convenience and pick desired columns
result <- temp[order(compid, date_crsp), .(compid, date_crsp)]

结果与预期的输出一致:
result
# compid date_crsp
# 1: 1 2
# 2: 1 3
# 3: 1 4
# 4: 1 5
# 5: 2 3
# 6: 2 4
# 7: 2 5
# 8: 2 6
# 9: 2 7
#10: 2 8
#11: 2 9
#12: 3 3
#13: 3 4
#14: 3 5
#15: 3 6
#16: 3 7
#17: 3 8

这可以用一行代码更简洁地编写:
foverlaps(
setkey(setDT(crsp_td_net)[, .(start = min(date_crsp), end = max(date_crsp)),
by = compid], start, end),
setkey(setDT(ff_35f)[, .(date_crsp, end = date_crsp)], date_crsp, end)
)[order(compid, start), .(compid, date_crsp)]

备注 OP 在他的 Q 中用整数替换了日期。 data.table包提供带有整数存储的日期和时间类,用于快速排序和分组(参见 ?as.IDate)。

关于R:更快地合并数据帧,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43431684/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com