如何解决使用API调用向量化R循环
我对向量化的概念还比较陌生,想问一下社区是否对改善我用来下载Bloomberg API数据并将其绑定到矩阵的流程的运行时间有任何建议。
当前,此过程会遍历我的API调用中的每个日期,这需要花费大量时间。我想知道是否可以“矢量化”的方式进行此操作,以便一次进行大量调用,然后绑定到数据帧,从而减少运行时间。 '''
#create fund names to feed through as param in loop below
fundList <- c("fund 1 on bloomberg","fund 2 on bloomberg","fund 3 on bloomberg","fund 4 on bloomberg","fund 5 on bloomberg","fund 6 on bloomberg","fund 7 on bloomberg",)
#create datelist for params for loop
newDateList <- seq(as.Date(today()-1401),length=1401,by="days")
newDateListReformatted <- gsub("-","",newDateList)
#create df object and loop through bloomberg API,assign to dataframe object
df_total = data.frame()
for(fund in 1:length(fundList)){
df_total = data.frame()
for(b in 1:length(newDateListReformatted)){
ovrd <- c("CUST_TRR_START_DT"=newDateListReformatted[b],"CUST_TRR_END_DT"=newDateListReformatted[b+1])
print(ovrd)
model <- bdp(fundList[fund],"CUST_TRR_RETURN_HOLDING_PER",overrides=ovrd)
print(model)
df <- data.frame(model)
df1 <- data.frame(newDateListReformatted[b+1])
df2 <- cbind(df,df1)
df_total <- rbind(df_total,df2)
}
assign(fundList[fund],df_total)
}
'''
首先,循环移动到第一级的某个基金,迭代所有日期,然后一次将行绑定到数据框,然后再移动到fundList中的下一个基金,并再次遍历时间序列。
以这种方式考虑,我将向函数调用多个日期参数的向量,然后“垂直”将它们一次分配给df_total矩阵,且每次分配的数目大于一个,并且每个循环都会增加运行时间。或者,我可以给每个单独的日期打电话,但要用很多资金来完成,然后将它们“水平”分配给矩阵。
任何想法都值得赞赏。
解决方法
向量化包含使我们具有有效实现每个输入的多个参数处理功能的功能。例如,可以使用循环lapply(mtcars,mean)
或使用向量化函数colMeans(mtcars)
计算列的平均值。后者比使用循环更有效,因为该功能针对输入进行了优化。
在堆栈溢出时,矢量化常常被误认为是代码readability
,因此通常使用*apply
函数被认为是矢量化,而这些功能对于可读性更有用,并且不能(单独)加速您的代码。
对于您的特定示例,瓶颈(和问题)部分来自对bdp
的调用,部分归因于使用cbind
,rbind
和{{1 }}。
为了加速您的代码,我们首先需要知道该函数是如何实现的。从文档中我们可以了解到assign
和fields
接受多个参数。因此,这些参数为securities
,而vectorized
仅接受覆盖字段的命名向量。这意味着我们可以通过一次性提供所有字段来消除代码中的外部循环。
接下来,为了通过迭代扩展overrides
来减少多次调用的开销,我们可以将中间结果存储在data.frame
中,然后组合输出。使用此代码,我们可以得到类似于以下代码的内容:
list
请注意,我最后使用n <- length(newDateListReformatted)
# Create override matrix (makes it easier to subset,but not strictly necessary
periods <- matrix(c(newDateListReformatted[-n],newDateListReformatted[-1]),ncol = 2,byrow = FALSE)
colnames(periods) <- c('CUST_TRR_START_DT','CUST_TRR_END_DT')
ovrds <- newDateListReformatted
models <- vector('list',n - 1)
for(i in seq_len(n - 1)){
models[[i]] <- bdp(fundList,'CUST_TRR_RETURN_HOLDING_PER',overrides = periods[i,]
)
# Add identifier columns
models[[i]][,'CUST_TRR_START_DT'] <- periods[i,1]
models[[i]][,'CUST_TRR_END_DT'] <- periods[i,2]
}
# Combine results in single data.frame (if wanted)
model <- do.call(rbind,models)
合并了结果,从而给出了一个do.call(rbind,models)
,但是可以使用data.frame
包或bind_rows
中的dplyr
也来自rbindlist
包。
还请注意,我目前无法访问Bloomberg,也无法测试我的代码是否存在拼写错误。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。