R:将列表列表转换为数据框(人口普查数据)

R: Converting a list of lists into a data frame (Census data)

我正在尝试使用人口普查 API 下载特定的 table 并将它们保存在数据框中。我已经成功下载数据了。我 assemble 适当的 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 向量,并且该向量包含 table 信息和关联的元数据。在这种情况下,我使用下面工作示例中的方法将列表转换为数据框,其中每一行是一个不同的空间单位,每一列是一个不同的变量。

# 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

但是当我对列表对象使用相同的方法时(这是因为我包含了来自 API 的不同 table),我收到一个错误:

# 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]

有人对此有解决方案吗?

备注

也许这就是您想要的:

simplify2array(l2)

编辑:

上述解决方案无效。作为替代方案,我会用 NA:

替换 NULL 值
# Function to replace NULL values to NA values inside a list
listNull2Na <- function(l) sapply(l, function(x) ifelse(is.null(x), NA, x))

# Substitute NULL values in your list and get matrix:
l2 <- sapply(l2, listNull2Na)

我给你一个使用真实查询的技巧:

tmp <- data.frame(matrix(ncol=4))

for(i in 1:length(data)){
  if(length(t(unlist(data[i]))) == 4){
  tmp[i,] <- t(unlist(data[i]))
  } else{
    cat("Row number ", i, "has an abnormal length \n")
  }
}
Row number  273 has an abnormal length 
Row number  550 has an abnormal length 
Row number  1900 has an abnormal length 
Row number  2733 has an abnormal length 
Row number  2737 has an abnormal length 
Row number  2753 has an abnormal length
head(tmp)
1                               NAME B19081_002M state county
2     Aleutians East Borough, Alaska        8469    02    013
3 Aleutians West Census Area, Alaska        7691    02    016
4     Anchorage Municipality, Alaska         920    02    020
5         Bethel Census Area, Alaska        2414    02    050
6        Bristol Bay Borough, Alaska        9635    02    060

超过 3,000 行中只有 6 行的长度不正常,但如果您想挽救这些行,可以通过添加另一行来用占位符填充缺失值来实现。

最后,别忘了第一行是header,所以你可以把它写到你的data.frame的colnames