我正在使用英国开发的用于从API提取fingertipsR
API数据包的过程中,从英国的公共卫生机构提取特定地理区域和特定指标的数据,然后将其插入空白列表,该列表由包含代表每个指标的列表的列表(地理区域)组成。
geog <- c("E38000220", "E38000046", "E38000144", "E38000191", "E38000210",
"E38000038", "E38000164", "E38000195", "E38000078", "E38000139",
"E38000166", "E38000211", "E38000147", "E38000183", "E38000028",
"E38000053", "E38000126", "E38000153", "E38000173", "E38000175"
)
indicators <- c(241, 92588, 90672, 90692, 90697, 90698, 90701, 90702, 91238,
90690, 90694, 93245, 93246, 93244, 93247, 93248, 93049, 93047,
90700)
## install.packages("fingertipsR"); library(fingertipsR)
library(dplyr)
list <- list()
start <- Sys.time()
for (geog_group in geog) {
for (indicator_number in indicators) {
list[[geog_group]][[as.character(indicator_number)]] <- fingertips_data(IndicatorID = indicator_number, AreaTypeID = c(152, 153, 154)) %>%
filter(AreaCode == geog_group, TimeperiodSortable == max(TimeperiodSortable)) %>%
select(Timeperiod, Value) %>% distinct()
}
}
end <- Sys.time()
end-start
在我的笔记本电脑上,这大约需要15分钟才能执行-我想知道是否有任何简便的方法可以优化此代码-可能使用lapply
或purrr
?
编辑:理想情况下,我希望每个地理区域的指标都在一个数据框中,因为它们共享相同的列Time period
和Value
-我将在{{之后处理1}}或类似的东西-但如果有人有办法在for循环内解决该问题,我欢迎您提出建议。
答案 0 :(得分:1)
这是一个更紧凑的循环(大约需要25秒)
result_list <- list(length(indicators))
for (k in seq_along(indicators)) {
ind <- indicators[k]
# load the data once per indicator
tmpDF <- fingertips_data(IndicatorID = ind, AreaTypeID = 152:154)
# retrieve the rows corresp. to max per geog
out <- t(vapply(seq_along(geog), function (s) {
row_geog <- which(.subset2(tmpDF, which(names(tmpDF) == 'AreaCode')) == geog[s])
row_max <- which.max(.subset2(tmpDF, which(names(tmpDF) == 'TimeperiodSortable'))[row_geog])
res <- tmpDF[row_geog,c("Timeperiod","Value")][row_max,]
res <- c(Timeperiod = res$Timeperiod, Value = res$Value)
if (length(res) == 0) res <- c(Timeperiod = NA_character_, Value = NA_character_)
return (res)
}, character(2)))
# save result for indicator[k]
result_list[[k]] <- data.frame(indicator = ind, geog,
Timeperiod = out[,1],
Value = as.numeric(out[,2]),
stringsAsFactors = FALSE)
}
我对fingertipsR
并不真正熟悉,但是似乎可以完成工作(如果我错了,请纠正我),这是结果的第一个要素:
head(result_list[[1]])
# indicator geog Timeperiod Value
# 1 241 E38000220 2017/18 8.214912
# 2 241 E38000046 2017/18 7.907130
# 3 241 E38000144 2017/18 9.139239
# 4 241 E38000191 2017/18 8.891195
# 5 241 E38000210 2017/18 8.311592
# 6 241 E38000038 2017/18 6.653444
更改
以下是我对您的版本所做的更改:
for
循环(严格来说,在我使用vapply
时,我的版本中还有两个循环)对指标进行了迭代。主要原因不是甚至没有更少的循环(它本身已经足够激励),而是尽可能少地调用函数fingertips_data
:这些函数调用非常慢,并且不依赖于{{1 }},只有子设置可以。geog
,函数indicator
被调用一次,然后使用fingertips_data
进行子设置并找到最大值