通过闪亮的 WDI 加载世界银行数据的有效方法
Efficiant way to load Wold Bank Data via WDI in shiny
我正在开发一个闪亮的仪表板项目,以可视化世界银行的数据。我总共需要 14 个不同的变量,我想在数据 table 中显示这些变量。它在 R 中有效,但是当我尝试在 shiny 中执行时,出现连接错误。我认为下载需要太多时间。
有没有办法更有效地或在后台加载数据或其他方式?我找不到使它成为 运行 的解决方案,并且我不想将数据存储在服务器上的文件中,因为这样我就没有自动更新...:/
这是一个最基本的重要代码片段
library(shiny)
library(dplyr)
library(WDI)
library(wbstats)
library(lubridate)
ui <- fluidPage(
titlePanel('WDI Example'),
mainPanel(tableOutput('table'))
)
server <- function(input, output) {
startDate <- as.numeric(format(Sys.Date(), "%Y")) -20
endDate <- as.numeric(format(Sys.Date(), "%Y"))
fetch.data <- list()
list <- c("SP.POP.TOTL",
"NY.ADJ.NNTY.PC.CD",
"SH.XPD.CHEX.PC.CD",
"SH.XPD.OOPC.CH.ZS",
"SH.MED.BEDS.ZS",
"SH.MED.PHYS.ZS",
"NY.GDP.MKTP.CD",
"NY.GDP.MKTP.KD",
"NY.GDP.MKTP.KD.ZG",
"SH.XPD.CHEX.GD.ZS",
"SP.DYN.LE00.IN",
"SP.POP.65UP.TO",
"SP.POP.DPND",
"SP.POP.DPND.OL")
for (i in 1:length(list)){
fetch.data[[i]] <- WDI(indicator = as.character(list[i]),
start = startDate,
end = endDate,
country = "all",
extra = TRUE)
}
data <- fetch.data
for (i in 1:length(list)){
data[[i]] <- subset(data[[i]], region != "Aggregates")
data[[i]] <- data[[i]] %>% select(country, iso3c, region, year, noquote(list[i]))
data[[i]]$date <- as.Date(as.character(date), format = "%Y")
data[[i]] <- data[[i]][complete.cases(data[[i]][ ,5]),]
data[[i]] <- data[[i]] %>% group_by(country) %>% arrange(desc(date)) %>% slice(1)
}
indicators <- fetch.data[[1]] %>%
select(country, iso3c, region) %>%
subset(region != "Aggregates") %>%
arrange(desc(country)) %>%
group_by(country) %>%
slice(1)
for (i in 1:length(list)){
indicators <- merge(indicators, data[[i]][ ,c(2,5)], by.x = "iso3c", by.y = "iso3c", all = TRUE)
}
indicators <- indicators %>%
arrange(country) %>%
mutate_if(is.numeric, round, 2)
output$table <- renderTable(indicators)
}
shinyApp(ui = ui, server = server)
这是一个不起作用的例子……https://thera-trainer.shinyapps.io/example/
谢谢指教
错误
你的错误在这行代码中:
data[[i]]$date <- as.Date(as.character(date), format = "%Y")
date
是一个函数(闭包),这就是您收到错误的原因。如果您要引用数据框中的列,则需要使用 data[[i]]$date
,如
data[[i]]$date <- as.Date(as.character(data[[i]]$date), format = "%Y")
您可能已经习惯了 tidyverse,您不需要在列的数据框前加上前缀,但在使用非 tidyverse 操作时,例如 <-
,您还必须包括数据框名称。此外,data[[i]]
中没有名为 date
的列,因此即使您使用了 as.Date(as.character(data[[i]]$date), format = "%Y")
,您也会收到错误消息,因为该列不存在。
此外,您似乎正在尝试将日期转换为年份,但 data[[i]]
中已经有一个名为 year
的列,您可以使用 [=23= 引用它].
代码风格
使用与函数名称相匹配的名称来命名对象不是好的做法。您已经完成了两次,一次是通过将 fetch.data
分配给 data
(已经有一个函数 utils::data()
,更重要的是,您已将指标分配给一个名为 list
的变量。这是 非常 危险的,因为您已经覆盖了全局环境中的 list()
函数,稍后要再次使用列表函数,您将不得不使用 [=29 调用它=]。我会为指标推荐一个更情绪化的名字,比如:
indicators_list <- c("SP.POP.TOTL",
"NY.ADJ.NNTY.PC.CD",
"SH.XPD.CHEX.PC.CD",
"SH.XPD.OOPC.CH.ZS",
"SH.MED.BEDS.ZS",
"SH.MED.PHYS.ZS",
"NY.GDP.MKTP.CD",
"NY.GDP.MKTP.KD",
"NY.GDP.MKTP.KD.ZG",
"SH.XPD.CHEX.GD.ZS",
"SP.DYN.LE00.IN",
"SP.POP.65UP.TO",
"SP.POP.DPND",
"SP.POP.DPND.OL")
withProgress
有一个 Shiny progress indicator 可以用来监视需要很长时间的循环。你会像这样包括它;
withProgress(
for (i in 1:length(indicators_list)){
incProgress(1/length(indicators_list), detail = paste("Doing part", i))
fetch.data[[i]] <- WDI(indicator = indicators_list[i],
start = startDate,
end = endDate,
country = "all",
extra = TRUE)
})
完整示例
这是我能够开始工作的完整示例。我只包含服务器组件,因为这是我进行更改的唯一组件。
server <- function(input, output) {
startDate <- as.numeric(format(Sys.Date(), "%Y")) -20
endDate <- as.numeric(format(Sys.Date(), "%Y"))
fetch.data <- list()
indicators_list <- c("SP.POP.TOTL",
"NY.ADJ.NNTY.PC.CD",
"SH.XPD.CHEX.PC.CD",
"SH.XPD.OOPC.CH.ZS",
"SH.MED.BEDS.ZS",
"SH.MED.PHYS.ZS",
"NY.GDP.MKTP.CD",
"NY.GDP.MKTP.KD",
"NY.GDP.MKTP.KD.ZG",
"SH.XPD.CHEX.GD.ZS",
"SP.DYN.LE00.IN",
"SP.POP.65UP.TO",
"SP.POP.DPND",
"SP.POP.DPND.OL")
withProgress(
for (i in 1:length(indicators_list)){
incProgress(1/length(indicators_list), detail = paste("Doing part", i))
fetch.data[[i]] <- WDI(indicator = indicators_list[i],
start = startDate,
end = endDate,
country = "all",
extra = TRUE)
})
data <- fetch.data
for (i in 1:length(indicators_list)){
data[[i]] <- subset(data[[i]], region != "Aggregates")
data[[i]] <- data[[i]] %>% select(country, iso3c, region, year, noquote(indicators_list[i]))
data[[i]]$date <- data[[i]]$year
data[[i]] <- data[[i]][complete.cases(data[[i]][ ,5]),]
data[[i]] <- data[[i]] %>% group_by(country) %>% arrange(desc(date)) %>% slice(1)
}
indicators <- fetch.data[[1]] %>%
select(country, iso3c, region) %>%
subset(region != "Aggregates") %>%
arrange(desc(country)) %>%
group_by(country) %>%
slice(1)
for (i in 1:length(indicators_list)){
indicators <- merge(indicators, data[[i]][ ,c(2,5)], by.x = "iso3c", by.y = "iso3c", all = TRUE)
}
indicators <- indicators %>%
arrange(country) %>%
mutate_if(is.numeric, round, 2)
output$table <- renderTable(indicators)
}
我正在开发一个闪亮的仪表板项目,以可视化世界银行的数据。我总共需要 14 个不同的变量,我想在数据 table 中显示这些变量。它在 R 中有效,但是当我尝试在 shiny 中执行时,出现连接错误。我认为下载需要太多时间。 有没有办法更有效地或在后台加载数据或其他方式?我找不到使它成为 运行 的解决方案,并且我不想将数据存储在服务器上的文件中,因为这样我就没有自动更新...:/
这是一个最基本的重要代码片段
library(shiny)
library(dplyr)
library(WDI)
library(wbstats)
library(lubridate)
ui <- fluidPage(
titlePanel('WDI Example'),
mainPanel(tableOutput('table'))
)
server <- function(input, output) {
startDate <- as.numeric(format(Sys.Date(), "%Y")) -20
endDate <- as.numeric(format(Sys.Date(), "%Y"))
fetch.data <- list()
list <- c("SP.POP.TOTL",
"NY.ADJ.NNTY.PC.CD",
"SH.XPD.CHEX.PC.CD",
"SH.XPD.OOPC.CH.ZS",
"SH.MED.BEDS.ZS",
"SH.MED.PHYS.ZS",
"NY.GDP.MKTP.CD",
"NY.GDP.MKTP.KD",
"NY.GDP.MKTP.KD.ZG",
"SH.XPD.CHEX.GD.ZS",
"SP.DYN.LE00.IN",
"SP.POP.65UP.TO",
"SP.POP.DPND",
"SP.POP.DPND.OL")
for (i in 1:length(list)){
fetch.data[[i]] <- WDI(indicator = as.character(list[i]),
start = startDate,
end = endDate,
country = "all",
extra = TRUE)
}
data <- fetch.data
for (i in 1:length(list)){
data[[i]] <- subset(data[[i]], region != "Aggregates")
data[[i]] <- data[[i]] %>% select(country, iso3c, region, year, noquote(list[i]))
data[[i]]$date <- as.Date(as.character(date), format = "%Y")
data[[i]] <- data[[i]][complete.cases(data[[i]][ ,5]),]
data[[i]] <- data[[i]] %>% group_by(country) %>% arrange(desc(date)) %>% slice(1)
}
indicators <- fetch.data[[1]] %>%
select(country, iso3c, region) %>%
subset(region != "Aggregates") %>%
arrange(desc(country)) %>%
group_by(country) %>%
slice(1)
for (i in 1:length(list)){
indicators <- merge(indicators, data[[i]][ ,c(2,5)], by.x = "iso3c", by.y = "iso3c", all = TRUE)
}
indicators <- indicators %>%
arrange(country) %>%
mutate_if(is.numeric, round, 2)
output$table <- renderTable(indicators)
}
shinyApp(ui = ui, server = server)
这是一个不起作用的例子……https://thera-trainer.shinyapps.io/example/
谢谢指教
错误
你的错误在这行代码中:
data[[i]]$date <- as.Date(as.character(date), format = "%Y")
date
是一个函数(闭包),这就是您收到错误的原因。如果您要引用数据框中的列,则需要使用 data[[i]]$date
,如
data[[i]]$date <- as.Date(as.character(data[[i]]$date), format = "%Y")
您可能已经习惯了 tidyverse,您不需要在列的数据框前加上前缀,但在使用非 tidyverse 操作时,例如 <-
,您还必须包括数据框名称。此外,data[[i]]
中没有名为 date
的列,因此即使您使用了 as.Date(as.character(data[[i]]$date), format = "%Y")
,您也会收到错误消息,因为该列不存在。
此外,您似乎正在尝试将日期转换为年份,但 data[[i]]
中已经有一个名为 year
的列,您可以使用 [=23= 引用它].
代码风格
使用与函数名称相匹配的名称来命名对象不是好的做法。您已经完成了两次,一次是通过将 fetch.data
分配给 data
(已经有一个函数 utils::data()
,更重要的是,您已将指标分配给一个名为 list
的变量。这是 非常 危险的,因为您已经覆盖了全局环境中的 list()
函数,稍后要再次使用列表函数,您将不得不使用 [=29 调用它=]。我会为指标推荐一个更情绪化的名字,比如:
indicators_list <- c("SP.POP.TOTL",
"NY.ADJ.NNTY.PC.CD",
"SH.XPD.CHEX.PC.CD",
"SH.XPD.OOPC.CH.ZS",
"SH.MED.BEDS.ZS",
"SH.MED.PHYS.ZS",
"NY.GDP.MKTP.CD",
"NY.GDP.MKTP.KD",
"NY.GDP.MKTP.KD.ZG",
"SH.XPD.CHEX.GD.ZS",
"SP.DYN.LE00.IN",
"SP.POP.65UP.TO",
"SP.POP.DPND",
"SP.POP.DPND.OL")
withProgress
有一个 Shiny progress indicator 可以用来监视需要很长时间的循环。你会像这样包括它;
withProgress(
for (i in 1:length(indicators_list)){
incProgress(1/length(indicators_list), detail = paste("Doing part", i))
fetch.data[[i]] <- WDI(indicator = indicators_list[i],
start = startDate,
end = endDate,
country = "all",
extra = TRUE)
})
完整示例
这是我能够开始工作的完整示例。我只包含服务器组件,因为这是我进行更改的唯一组件。
server <- function(input, output) {
startDate <- as.numeric(format(Sys.Date(), "%Y")) -20
endDate <- as.numeric(format(Sys.Date(), "%Y"))
fetch.data <- list()
indicators_list <- c("SP.POP.TOTL",
"NY.ADJ.NNTY.PC.CD",
"SH.XPD.CHEX.PC.CD",
"SH.XPD.OOPC.CH.ZS",
"SH.MED.BEDS.ZS",
"SH.MED.PHYS.ZS",
"NY.GDP.MKTP.CD",
"NY.GDP.MKTP.KD",
"NY.GDP.MKTP.KD.ZG",
"SH.XPD.CHEX.GD.ZS",
"SP.DYN.LE00.IN",
"SP.POP.65UP.TO",
"SP.POP.DPND",
"SP.POP.DPND.OL")
withProgress(
for (i in 1:length(indicators_list)){
incProgress(1/length(indicators_list), detail = paste("Doing part", i))
fetch.data[[i]] <- WDI(indicator = indicators_list[i],
start = startDate,
end = endDate,
country = "all",
extra = TRUE)
})
data <- fetch.data
for (i in 1:length(indicators_list)){
data[[i]] <- subset(data[[i]], region != "Aggregates")
data[[i]] <- data[[i]] %>% select(country, iso3c, region, year, noquote(indicators_list[i]))
data[[i]]$date <- data[[i]]$year
data[[i]] <- data[[i]][complete.cases(data[[i]][ ,5]),]
data[[i]] <- data[[i]] %>% group_by(country) %>% arrange(desc(date)) %>% slice(1)
}
indicators <- fetch.data[[1]] %>%
select(country, iso3c, region) %>%
subset(region != "Aggregates") %>%
arrange(desc(country)) %>%
group_by(country) %>%
slice(1)
for (i in 1:length(indicators_list)){
indicators <- merge(indicators, data[[i]][ ,c(2,5)], by.x = "iso3c", by.y = "iso3c", all = TRUE)
}
indicators <- indicators %>%
arrange(country) %>%
mutate_if(is.numeric, round, 2)
output$table <- renderTable(indicators)
}