可持续发展目标(SDGs)是联合国在2015年提出的全球发展议程,包含17个大目标和数百项具体指标。这些指标的实际数值大部分通过联合国统计司维护的UN Data平台对外发布。如果只是偶尔查几个数字,直接在网页上导出Excel就够了,但要做持续跟踪、跨指标建模或者构建自动化报表,就必须学会通过API批量抓取。R语言在统计分析和数据可视化方面优势明显,配合几个成熟的HTTP与JSON处理包,可以快速搭起一条从数据获取到分析出图的完整管线。

一、UN Data API的接口结构与请求规则
UN Data的API入口地址是 http://data.un.org/WS/rest,这是一个遵循SDMX标准的REST接口。SDMX(Statistical Data and Metadata Exchange)是国际统计机构通用的数据交换规范,很多国际组织如IMF、世界银行、OECD都支持这套标准,所以学会调用UN Data的API,迁移到其他组织的数据源也基本是同一套思路。
接口主要分两类资源:一类是数据流(dataflow),可以理解为一个个数据集的目录,比如人口统计、国民账户、SDG指标库等;另一类是具体数据(data),通过指定数据流ID加上维度过滤条件获取数值。先请求 http://data.un.org/WS/rest/dataflow/ALL/all/latest 可以拿到全部可用数据流的清单,从返回结果里找到包含SDG关键词的数据流即可。
返回格式支持XML和JSON两种。SDMX原生是XML,但对R用户来说JSON处理起来更省事,只需在请求头中设置 Accept: application/json,或者在URL后追加查询参数,服务端就会返回JSON结构。需要注意的是,UN Data对请求频率有限制,官方建议控制在每秒一次以内,短时间内高频请求可能被暂时封禁IP,后面会讲如何用限速函数规避。
二、用R构造请求并解析返回数据
构造HTTP请求推荐使用 httr2 包,它是 httr 的升级版本,支持请求管道式构建和自动重试,写法更清晰。解析JSON则交给 jsonlite。先安装并加载这两个包:
install.packages(c("httr2", "jsonlite", "dplyr", "ggplot2"))
library(httr2)
library(jsonlite)
library(dplyr)
library(ggplot2)
第一步获取数据流清单,从中筛选出可持续发展目标相关的数据集:
# 获取全部数据流清单,返回JSON
flows <- request("http://data.un.org/WS/rest/dataflow/ALL/all/latest") |>
req_headers(Accept = "application/json") |>
req_perform() |>
resp_body_json(simplifyVector = TRUE)
# 查看结构,筛选包含SDG的数据流
flow_df <- flows$dataflows
sdg_flows <- flow_df[grepl("SDG|Sustainable", flow_df$name, ignore.case = TRUE), ]
head(sdg_flows[, c("id", "name")])
第二步是请求数据本身。SDMX的数据查询URL格式是 data/{数据流ID}/{维度过滤},维度之间用点号分隔,例如某个SDG数据流的指标维度、国家维度、时间维度可以组合过滤。下面以一个示例数据流为例,抓取部分国家在特定指标上的历史序列:
base <- "http://data.un.org/WS/rest/data" url <- paste0(base, "/DF_SDG_HLY/ALL.A.US.CA.CHN.DEU") raw <- request(url) |> req_headers(Accept = "application/json") |> req_throttle(rate = 1 / 2) |> # 每2秒最多一次请求,主动限速 req_retry(max_tries = 3) |> # 失败自动重试 req_perform() dat <- resp_body_json(raw, simplifyVector = TRUE)
返回的JSON结构里,数值和维度信息是分开存放的。series部分放维度组合,observations部分放年份和数值,需要手动把两者拼起来变成整洁的长表。这一步是整个流程中最容易出错的地方,因为不同数据流的维度数量不一样,建议写一个通用函数处理:
flatten_sdmx <- function(dat) {
series <- dat$data$series
result <- lapply(seq_along(series), function(i) {
s <- series[[i]]
obs <- s$observations
# 每个观测对应一个年份和一个数值
years <- names(obs)
values <- sapply(obs, function(x) as.numeric(x[1]))
data.frame(
series_key = names(series)[i],
year = as.integer(years),
value = values,
stringsAsFactors = FALSE
)
})
bind_rows(result)
}
long_df <- flatten_sdmx(dat)
head(long_df)
这里有一个实战建议:拿到数据后先检查 value 列的缺失比例。国际组织的数据往往存在明显的报告滞后,近一两年的数据可能大面积为空,做趋势图时要么截断到最后一个有值的年份,要么在图上明确标注数据边界,避免误导读者。
三、可持续发展指标的分析与可视化
数据变成整洁的长表之后,分析环节就回到R最熟悉的领域了。以极端贫困率这一SDG 1的核心指标为例,可以对比不同国家自2000年以来的下降趋势:
ggplot(long_df, aes(x = year, y = value, color = series_key)) +
geom_line(linewidth = 1) +
geom_point(size = 1.5) +
labs(
title = "部分国家极端贫困率变化趋势",
x = "年份", y = "指标值",
color = "国家序列"
) +
theme_minimal()
如果抓取了多个指标,还可以做一个横向对比表。常见做法是用 tidyr::pivot_wider 把长表转宽表,每个指标一列,再配合 gt 包生成可发布的统计表格。需要注意不同指标的量纲差异很大,可再生能源占比是百分比,碳排放量是百万吨,直接画在同一张图上没有意义,要先做标准化或者拆成多个子图(facet)。
对于需要定期更新的场景,可以把抓取脚本封装成函数,配合 targets 包构建可复现的分析流水线,每次运行只重新抓取有变化的数据流。再加上 httr2 自带的缓存机制,重复请求相同URL时会直接读取本地缓存,既减轻服务器压力也加快本地迭代速度。这套方案稍加扩展,就能覆盖世界银行API、OECD数据等其他国际数据源,形成统一的全球宏观研究数据底座。
四、常见问题与避坑要点
第一个坑是编码问题。部分国家名称和数据集描述中带有重音字符,如果Windows环境下出现乱码,可以在脚本开头执行 Sys.setlocale("LC_ALL", "Chinese"),并用 readr 系列函数处理字符串,避免默认编码不一致导致的乱码。
第二个坑是数据流ID的变动。联合国统计司偶尔会调整数据流命名,硬编码在脚本里的ID可能某天突然失效。稳妥的做法是把数据流清单的获取也纳入脚本,每次运行时动态匹配名称,找不到时报出明确的错误信息而不是静默返回空表。
第三个坑是JSON结构层级的不确定性。不同数据流的返回结构在维度数量和属性字段上有差异,写解析函数时不要假设层级固定不变,多用 str() 检查实际结构,必要时对 NULL 做防御性处理,比如 sapply(obs, function(x) if (is.null(x)) NA else as.numeric(x[1])),这样即使某条观测缺失也不会让整个解析中断。
整体来看,UN Data API配合R语言的组合,是做全球宏观与可持续发展研究的低成本方案。接口免费、数据权威、更新及时,只要处理好限速和解析这两个环节,就能建立起一套稳定的数据管线,支撑从快速查数到深度建模的各种需求。
R语言UN Data API可持续发展指标修改时间:2026-09-14 06:39:42