我正在尝试使用美国劳工统计局的所有美国县失业数据创建一个data.frame:
http://www.bls.gov/lau/#cntyaa
从1990年到2013年,数据每年有一个结果。
我最初计划使用BLS API,但看起来他们认为每个县都是一个单独的查询,并且查询总数将超过其阈值。我现在认为简单地从他们放在网上的TXT文件中抓取数据可能更容易,但我在使用R解析数据时遇到问题。这是一个包含数据的示例页面:
http://www.bls.gov/lau/laucnty90.txt#90 = 1990
我最初尝试使用rvest
包解析文件。但由于数据都在一个<p>
标签中,我认为该工具的表格没有足够的HTML结构。
然后我尝试了download.file
和read.table
。但同样,这些工具的数据似乎不是正确的格式 - 顶部和底部的额外线条,以及分离字符&#34;只是一个空间,当县名包含空格时,它会混淆R.
在一天结束时,我只需要一个包含此文件中3个数据的data.frame:状态FIPS代码,县FIPS代码和失业率。
我现在认为创建此data.frame的最简单方法可能是下载excel文件,删除我不需要的列,删除顶部和底部的额外文本,导出到CSV,然后将其读入R.
我可以在14年中的每一年都这样做。但是我失去了一些可重复性 - 其他人无法轻易验证我在导入过程中没有犯错误。
有没有人看到更简单的方法来创建这个data.frame?
答案 0 :(得分:6)
这只是一个固定宽度的数据文件。我没有时间为您提供完美的代码,但调整此代码可以为您提供所需的代码:
url = 'http://www.bls.gov/lau/laucnty90.txt'
w = c(17, 8, 6, 50, 12, 13, 12, 11)
dat = read.fwf(url, w, skip=3)
答案 1 :(得分:3)
需要一个“标尺”来确定要拆分的列:
cat(">",paste0(rep(c(1:9,"+"),14),collapse=""))
cat(">",paste0(sprintf("%08s0/",1:14),collapse=""))
> 123456789+123456789+123456789+123456789+123456789+123456789+123456789+123456789+123456789+123456789+123456789+123456789+123456789+123456789+
cat(">",paste0(sprintf("%08s0/",1:14),collapse=""))
> 000000010/000000020/000000030/000000040/000000050/000000060/000000070/000000080/000000090/000000100/000000110/000000120/000000130/000000140/
# and paste in the first line of data
> CN0100100000000 01 001 Autauga County, AL 1990 16,875 15,853 1,022 6.1
这可以让你找出放置拆分的位置并获取不同的值并移动一个值得到宽度。跳过前六行,然后处理读入的数据作为字符,以避免因素的麻烦。在强制转换为数字之前删除逗号。
> dat = read.fwf(url,
widths=diff(c(0,16,21,29,80,86,100,115,125,132)+1),
skip=6,colClasses="character")
> str(dat)
'data.frame': 3219 obs. of 9 variables:
$ V1: chr "CN0100100000000 " "CN0100300000000 " "CN0100500000000 " "CN0100700000000 " ...
$ V2: chr " 01 " " 01 " " 01 " " 01 " ...
$ V3: chr " 001 " " 003 " " 005 " " 007 " ...
$ V4: chr " Autauga County, AL " " Baldwin County, AL " " Barbour County, AL " " Bibb County, AL " ...
$ V5: chr " 1990 " " 1990 " " 1990 " " 1990 " ...
$ V6: chr " 16,875 " " 46,773 " " 11,458 " " 7,408 " ...
$ V7: chr " 15,853 " " 44,492 " " 10,619 " " 6,776 " ...
$ V8: chr " 1,022 " " 2,281 " " 839 " " 632 " ...
$ V9: chr " 6.1" " 4.9" " 7.3" " 8.5" ...
dat[6:8] <- lapply( dat[6:8],
function(col) as.numeric( gsub("[,]", "", col)) )
> str(dat)
'data.frame': 3219 obs. of 9 variables:
$ V1: chr "CN0100100000000 " "CN0100300000000 " "CN0100500000000 " "CN0100700000000 " ...
$ V2: chr " 01 " " 01 " " 01 " " 01 " ...
$ V3: chr " 001 " " 003 " " 005 " " 007 " ...
$ V4: chr " Autauga County, AL " " Baldwin County, AL " " Barbour County, AL " " Bibb County, AL " ...
$ V5: chr " 1990 " " 1990 " " 1990 " " 1990 " ...
$ V6: num 16875 46773 11458 7408 19130 ...
$ V7: num 15853 44492 10619 6776 18001 ...
$ V8: num 1022 2281 839 632 1129 ...
$ V9: chr " 6.1" " 4.9" " 7.3" " 8.5" ...
dat[[9]] <- as.numeric( dat[[9]])
这可以通过使用一些“NULL”
来改善答案 2 :(得分:3)
这是一个使用XLConnect
包直接读取电子表格的选项,避免了所有这些确定列边界的业务。
get.file <- function(url) {
require(XLConnect)
download.file(url,"temp.xlsx",mode="wb")
wb <- loadWorkbook("temp.xlsx")
ws <- readWorksheet(wb,1,startRow=7,header=FALSE,drop=list(6))
ws[!is.na(ws$Col2),] # remove empty rows at the end
}
pfx <- "http://www.bls.gov/lau/laucnty"
urls <- paste0(pfx,c(90:99,formatC(0:13,width=2,flag=0)),".xlsx")
result <- do.call(rbind,lapply(urls,get.file))
head(result)
# Col1 Col2 Col3 Col4 Col5 Col7 Col8 Col9 Col10
# 1 CN0100100000000 01 001 Autauga County, AL 1990 16875 15853 1022 6.1
# 2 CN0100300000000 01 003 Baldwin County, AL 1990 46773 44492 2281 4.9
# 3 CN0100500000000 01 005 Barbour County, AL 1990 11458 10619 839 7.3
# 4 CN0100700000000 01 007 Bibb County, AL 1990 7408 6776 632 8.5
# 5 CN0100900000000 01 009 Blount County, AL 1990 19130 18001 1129 5.9
# 6 CN0101100000000 01 011 Bullock County, AL 1990 4381 3869 512 11.7
在readWorksheet(...)
调用中,我们跳过前7行,因为它们包含标题,我们删除第6列,因为它是空白的。然后我们删除第2列中包含NA
的结果中的所有行(最后几行是注释)。最后,我们使用lapply(...)
创建所有提取文件的列表,并使用do.call(rbind,...)
将它们全部按行组合。
请注意,所有列都是字符。你还需要做一些清理工作。与这些数十年的数据集一样,一些数据缺失,“缺失”的代码并不总是相同(有时为"NA"
,有时为"N.A."
等。)