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]
有人对此有解决方案吗?
- 我注意到子列表仅在其中一个变量具有 NULL 值的情况下出现。
- 在主列表的元素也是列表的情况下,子列表的长度等于主列表元素的向量长度。
备注
- 我不需要使用 fromJSON,欢迎使用可能使这更容易的替代方案。
- 我不想使用 'acs' 包来完成这个,所以请不要建议使用它。我正在努力学习如何处理这个问题。
也许这就是您想要的:
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
。
我正在尝试使用人口普查 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]
有人对此有解决方案吗?
- 我注意到子列表仅在其中一个变量具有 NULL 值的情况下出现。
- 在主列表的元素也是列表的情况下,子列表的长度等于主列表元素的向量长度。
备注
- 我不需要使用 fromJSON,欢迎使用可能使这更容易的替代方案。
- 我不想使用 'acs' 包来完成这个,所以请不要建议使用它。我正在努力学习如何处理这个问题。
也许这就是您想要的:
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
。