0

我正在尝试使用 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”包来完成这个,所以请不要建议使用它。我正在尝试学习如何处理这个问题。
4

2 回答 2

2

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

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 个具有异常长度,但如果您想要挽救这些行,可以通过添加另一行来使用占位符填充缺失值来实现。

最后,别忘了第一行是一个标题,所以你可以把它写到colnames你的data.frame中。

于 2016-07-17T21:47:24.430 回答
0

也许这就是你所追求的:

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)
于 2016-07-17T21:42:04.877 回答