将世界银行WITS接口返回的XML数据转换为DataFrame
将WITS API返回的XML数据转换为指定结构的R DataFrame
问题背景
通过以下R代码调用世界银行WITS API获取贸易数据:
u <- paste0("https://wits.worldbank.org/API/V1/SDMX/V21/datasource/", "tradestats-trade/reporter/isr/year/1990;2024/partner/alb/product/total/indicator/XPRT-TRD-VL") p <- httr::GET(u) %>% httr::content("text", encoding="UTF-8") xmlParse(p)
返回的XML数据中,Series节点包含全局属性(FREQ、REPORTER等),Obs节点包含逐年的时间和数值数据,需要将这些数据整合为包含FREQ、REPORTER、PARTNER、PRODUCTCODE、INDICATOR、TIME_PERIOD、OBS_VALUE列的DataFrame。
解决方案
以下提供两种实现方式,选择其中一种即可:
方法一:使用xml2包(推荐,语法更简洁)
library(xml2) library(dplyr) # 解析XML内容 xml_doc <- read_xml(p) # 提取Series节点的全局属性 series_attrs <- xml_attrs(xml_find_first(xml_doc, ".//Series")) # 提取所有Obs节点的属性并转为数据框 obs_df <- purrr::map_dfr(xml_find_all(xml_doc, ".//Obs"), ~as.list(xml_attrs(.x))) # 合并全局属性与观测数据,调整列顺序和数据类型 final_df <- obs_df %>% mutate( FREQ = series_attrs["FREQ"], REPORTER = series_attrs["REPORTER"], PARTNER = series_attrs["PARTNER"], PRODUCTCODE = series_attrs["PRODUCTCODE"], INDICATOR = series_attrs["INDICATOR"] ) %>% select(FREQ, REPORTER, PARTNER, PRODUCTCODE, INDICATOR, TIME_PERIOD, OBS_VALUE) %>% mutate( TIME_PERIOD = as.integer(TIME_PERIOD), OBS_VALUE = as.numeric(OBS_VALUE) ) # 查看结果 print(final_df)
方法二:使用XML包(兼容原有代码)
library(XML) library(dplyr) # 解析XML文档 xml_doc <- xmlParse(p) xml_root <- xmlRoot(xml_doc) # 获取Series节点及其全局属性 series_node <- xmlRoot(xml_root[["DataSet"]])[["Series"]] series_attrs <- xmlAttrs(series_node) # 提取每个Obs节点的属性并合并全局属性 obs_list <- lapply(xmlChildren(series_node), function(node) { c(series_attrs, xmlAttrs(node)) }) # 转换为DataFrame并调整结构 final_df <- bind_rows(obs_list) %>% select(FREQ, REPORTER, PARTNER, PRODUCTCODE, INDICATOR, TIME_PERIOD, OBS_VALUE) %>% mutate( TIME_PERIOD = as.integer(TIME_PERIOD), OBS_VALUE = as.numeric(OBS_VALUE) ) # 查看结果 print(final_df)
说明
- 两种方法都会将
Series节点的公共属性(FREQ、REPORTER等)添加到每一行观测数据中 - 最终DataFrame会自动调整列顺序,并将
TIME_PERIOD转为整数、OBS_VALUE转为数值类型,方便后续分析
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

