【问题标题】:Splitting values with no delimiter and uneven lengths拆分没有分隔符和不均匀长度的值
【发布时间】:2019-02-17 10:46:25
【问题描述】:

我从以下站点抓取了第二个 HTML 表格

(http://www.floridahealth.gov/programs-and-services/office-of-medical-marijuana-use/medical-marijuana-treatment-centers/index.html)

下面是我提取表格的代码:

   FLlist <- read_html("http://www.floridahealth.gov/programs-and- 
services/office-of-medical-marijuana-use/medical-marijuana-treatment- 
centers/index.html")

FLDispensaries <- as.data.frame(FLlist %>%
  html_nodes("table") %>%
  .[[2]] %>%
  html_table(header = TRUE))

write.csv(FLtest, "FLTest.csv")

表格填充在 Excel 中,如下所示:List after is written as a CSV

我想分隔地址信息,但长度或分隔符不一致。这个列表将继续增长,我在其他数据集上遇到了同样的问题,所以我想编写一个代码来自动化分离地址数据的过程。也许我一开始就可以在刮桌子的时候做到这一点?

【问题讨论】:

  • I want to separate the address info 怎么样?请解释并展示您到目前为止所做的尝试。

标签: r split gsub tidyr strsplit


【解决方案1】:

由于您尚未指定要如何分隔地址,我假设地址块中的每一行都应转到单独的列。
为此,您可以使用足够的 XPath 查询来选择第二个表的 p-tags,例如

//*[@id="DispensingFacilities"]/tbody/tr/td/p/text()

然后遍历结果并从头开始创建表结构。以这种方式生成 CSV 现在有点复杂。有几种方式,如下图一种:

library(xml2)
library(magrittr)
library(rvest)

FLlist <- read_html("http://www.floridahealth.gov/programs-and-services/office-of-medical-marijuana-use/medical-marijuana-treatment-centers/index.html")

FLDispensaries <- as.data.frame(FLlist %>%
                                  html_nodes("table") %>%
                                  .[[2]] %>%
                                  html_table(header = TRUE))

FLTable <- html_nodes(x=FLlist, xpath='//*[@id="DispensingFacilities"]/tbody/tr/td/p/text()')

#helper
trim <- function (x) gsub("^\\s+|\\s+$", "", x)

mat<-matrix(list(), ncol=4)
li <- c()
row <- 0;
col <- 1;
for(i in FLTable){
  li <- c(li,trim(html_text(i)));
  if(col %% 4 == 0) {
    row <- row + 1;
    mat[[row]] <- li;
    li <- c();
  }
  col <- col + 1;
}
#to matrix/list to dataframe
library(plyr)
mat.df <- as.data.frame(do.call(rbind, mat))
write.csv(mat.df, "FLTest.csv")

由于您只想获得实际地址,因此我将 XPath 更改为仅从第二个 tr 开始选择第二个 td

FLTable <- html_nodes(x=FLlist, xpath='//*[@id="DispensingFacilities"]/tbody/tr[position()>1]/td[2]/p')

li <- c()
row <- 1;
mat<-matrix(list(), ncol=2)
for (i in seq_along(FLTable)) {
  addrlines <- str_split(xml_text(FLTable[[i]]), "\\s\\s")
  for (a in seq_along(addrlines[[1]])) {
    if(a %% 2 == 0) {
      li <- c(li,paste(addrlines[[1]][a], addrlines[[1]][a+1]));
      mat[[row]] <- li;
      li <- c();
      row <- row + 1;
    } else if(a %% 3 == 0) {
      next; #skip
    } else {
      li <- c(li,addrlines[[1]][a]);
    }
  }
}

并创建一个不错的输出

outputFile <- "output.csv"
#to matrix/list to dataframe
mat.df <- as.data.frame(do.call(rbind, mat))
cat(c("No.,", "Name,", "Address"), '\n',  file = outputFile)
write.table(mat.df,outputFile,sep=',',append = T, col.names = F)

生成的 CSV 如下所示:

No., Name, Address 
"1","AltMed Florida (MuV)","5909 U.S. Hwy 41 N Apollo Beach, FL 33572"
"2","Trulieve","1103 14th Street West Bradenton, FL 34205"
...
"55","Trulieve","1814 Commerce Avenue Vero Beach, FL 32960"

【讨论】:

  • 这很有帮助。关于您上面的问题,我试图拍摄我在问题中提供的图像,并打破地址前面提供的名称。所以 AltMed Florida (MuV)、Trulieve、Curaleaf 等将在他们自己的列中,然后地址信息将在自己的列中。通常我想把街道信息、城市、州和邮编放在一个单独的列中。
  • 另外,我会投票赞成答案,但由于我是新手,现在不允许我投票。
  • @WillHolt 我很高兴这对您有所帮助。你是对的,你不能upvote yet, just accept
  • 老实说,我自己还无法解决这个问题,所以如果您不介意帮助,我将不胜感激。
猜你喜欢
  • 1970-01-01
  • 2016-10-10
  • 2016-08-02
  • 2020-08-24
  • 1970-01-01
  • 2018-03-31
  • 2021-12-23
  • 2021-08-25
  • 2019-10-05
相关资源
最近更新 更多