【问题标题】:Creating a data.frame with all USA County Unemployment Data使用所有美国县失业数据创建一个 data.frame
【发布时间】:2015-01-03 18:33:09
【问题描述】:

我正在尝试使用来自美国劳工统计局的所有美国县失业数据创建一个 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.fileread.table。但同样,这些工具的数据格式似乎不正确 - 顶部和底部有多余的行,“分隔符”只是一个空格,当县名包含空格时,这会使 R 混淆。

归根结底,我只需要一个包含来自该文件的 3 条数据的 data.frame:州 FIPS 代码、县 FIPS 代码和失业率。

我现在认为创建此 data.frame 的最简单方法可能是下载 excel 文件,删除我不需要的列,删除顶部和底部的多余文本,导出为 CSV,然后然后将其读入 R。

我当然可以在 14 年中的每一年都做到这一点。但是我因此失去了一些可重复性 - 其他人将无法轻松验证我在导入过程中没有犯错。

有没有人发现创建此 data.frame 的更简单方法?

【问题讨论】:

    标签: r rvest


    【解决方案1】:

    这只是一个固定宽度的数据文件。我没有时间给你完美的代码,但是调整一下应该可以满足你的需求:

    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)
    

    【讨论】:

    • 我以前从来没有用过fixed-with文件格式!谢谢!
    • 这与@BondedDust 的回答有何不同?
    • 没有什么不同。刚刚发布过。
    • 从某种意义上说,它并没有根本的不同,但它实际上的不同之处在于它提供了因子和错误的列数。
    【解决方案2】:

    需要一个“标尺”来确定要拆分的列:

    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”来改善

    【讨论】:

      【解决方案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.",等等)。

      【讨论】:

        猜你喜欢
        • 2020-07-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-09-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多