【发布时间】:2016-11-20 10:09:39
【问题描述】:
我正在尝试使用 Census API 下载特定表格并将其保存在数据框中。我已经成功下载了数据。我为调用组装了适当的 URL,然后使用包 'rjson' 将 URL 读入列表中。例如:
library(rjson)
get <- c("B19081_002M") # create vector of vars
datafile <- "http://api.census.gov/data/2009/acs5?" # ACS 05-09
get <- paste0("get=NAME,", paste(get, collapse = ',')) # variables
geo <- "for=county:*" # all counties
api_key <- "key=KEYHERE" # API key
url <- paste0(datafile, paste(get, geo, api_key, sep = "&")) # creates url
data <- fromJSON(file = url) # read into R
# To see an example of a problematic observation
# (this should return "Hinsdale County, Colorado")
data[[273]]
但是,我很难将其转换为数据框。 fromJSON() 函数创建一个列表对象。在大多数情况下,列表对象的元素是每个空间单元(例如上例中的县)的 chr 向量,并且该向量包含表信息和关联的元数据。在这种情况下,我使用以下工作示例中的方法将列表转换为数据框,其中每一行是不同的空间单位,每一列是不同的变量。
# Create fake data
x1 <- seq(1:5)
x2 <- rep(5,5)
l1 <- list(x1,x2)
# Convert to df
cols_per_row <- length(unlist(l1[1]))
test1 <- data.frame(matrix(unlist(l1), byrow = TRUE, ncol = cols_per_row))
print(test1) # success!
X1 X2 X3 X4 X5
1 1 2 3 4 5
2 5 5 5 5 5
但是当我对 list-in-list 对象使用相同的方法时(这是因为我从 API 中包含了不同的表而出现),我收到一个错误:
# Create fake data
x1 <- seq(1:5)
x2 <- rep(5,5)
x3 <- list(1,2,3,4,NULL)
l2 <- list(x1,x2,x3)
# Produces an error
cols_per_row <- length(unlist(l2[1]))
test2 <- data.frame(matrix(unlist(l2), byrow = TRUE, ncol = cols_per_row))
Warning message:
In matrix(unlist(l2), byrow = TRUE, ncol = cols_per_row) :
data length [14] is not a sub-multiple or multiple of the number of columns [5]
有人对此有解决方案吗?
- 我注意到子列表仅在变量之一具有 NULL 值的情况下出现。
- 在主列表的元素也是列表的情况下,子列表的长度等于作为向量的主列表元素的向量长度。
备注
- 我不需要使用 fromJSON 并且欢迎使用可能使这更容易的替代方法。
- 我不想使用“acs”包来完成这个,所以请不要建议使用它。我正在努力学习如何处理这个问题。
【问题讨论】:
-
as.data.frame(do.call(cbind, l2))将是一种典型的(虽然不是很好;你会丢失类型)方式。purrr对于处理列表很有用;你可以做类似l2 %>% setNames(make.names(seq_along(.))) %>% at_depth(2, ~.x %||% NA) %>% map_df(unlist)的事情,虽然这可能不是最优雅的版本。
标签: json r list dataframe census