簡體   English   中英

從R中的字符向量創建數據幀

[英]Creating a data frame from a character vector in R

我有一些文本格式的數據,取自網頁。 它很長,但是遵循以下形式:

<p><span class="monthyear">Jan 2001</span>
<br><b>Foo text (2)</b></p>
<p><span class="monthyear">Nov 2006</span>
<br><b>Bar text (29)</b>
<br><b>More bar text (4)</b>
<br><b>Yet more bar text (102)</b></p>
<p><span class="monthyear">Apr 2004</span>
<br><b>Further foo text (1)</b>
<br><b>Combination foo and bar text (41)</b></p>

我想將其相關部分提取到數據框中,如下所示:

  monthyear          info  n
1  Jan 2001      Foo text  2
2  Nov 2006      Bar text 29
3  Nov 2006 More bar text  4

...但是我不確定該怎么做。 如果我有一個特征向量稱為文字的HTML我可以使用函數從stringr包中提取monthyear數據:

monthyear <- str_extract_all(
text[1],perl("(?<=\\\"monthyear\\\">).*?20[0-9]{2}")
)

而且我可以用相同的方式提取信息n個數據,但是鑒於每個月年條目都有多個信息n個條目,因此我不確定如何將它們組合在一起。 我要解決所有這些錯誤嗎?

不幸的是,我們不能總是控制數據源的質量,因此我們不得不求助於一些繁瑣的手動處理。 (有人說,數據分析師的大部分時間都花在清理數據上,而不是在分析上。)

正如評論中已經指出的那樣,正則表達式並不是使用HTML的最佳工具,因為一般來說HTML並不是真正的正則語言(我認為這是上下文無關的語言 )。 但是,如果HTML源代碼有些規律 (如您所提供的示例數據中的代碼),則您仍然可以有效地使用它們。

這是一個分步示例。 我已將HTML標頭標簽添加到您的示例文本中,並將其存儲在此處: http : //ideone.com/O1PC05

  1. 使用readLines讀入數據

     x1 <- readLines("http://ideone.com/plain/O1PC05") 
  2. 隔離網頁的“正文”

     bodycontent <- grep("<body>|</body>", x1) x2 <- x1[(bodycontent[1]+1):(bodycontent[2]-1)] 
  3. 如果在給定的行中找到“ grepl ”,則grepl返回TRUEFALSE 使用cumsum創建“組”,然后split以將字符向量轉換為列表。

     x3 <- split(x2, cumsum(grepl("monthyear", x2))) 
  4. 如果願意,可以分多個步驟執行以下操作。 基本思想是lapply您的列表,將所有HTML標記替換為選項卡,並將方括號替換為選項卡。 之后,您可以使用read.delim ,但是由於我們插入的標簽數量超出了我們的需要,因此期望獲得很多NA值都為FULL的列。

    這很可能會因多種原因而失敗。 (1)假設源數據確實結構良好...(2)但是文本本身可能帶有括號...(3)或正文中可能還有其他內容,包括腳本標簽,表格標簽,依此類推,將其讀入並嘗試進行處理。

     x4 <- read.delim(header = FALSE, stringsAsFactors = FALSE, strip.white = TRUE, sep = "\\t", text = unlist(lapply(x3, function(x) { temp <- gsub("<(.|\\n)*?>", "\\t", x) paste(gsub("[()]", "\\t", temp), collapse="\\t") }))) 
  5. 我在第4步中提到過,我們將得到很多垃圾列。 讓我們擺脫這些。

     x5 <- x4[apply(x4, 2, function(x) !all(is.na(x)))] 
  6. 現在,讓我們以更有意義的方式命名列。 我們知道,第一列將是設計了“monthyear”變量,和其他人應該是“信息”和“n”,所以我們可以做一些基本的rep小號包裹在paste ,讓我們的變量名。 雖然我們在這,我們將使用as.yearmon從“動物園”包到我們的“monyear”變量轉換為實際日期,使我們能夠梳理和做其他時髦的東西,我們可以與實際日期做。

     myseq <- ncol(x5[-1])/2 # We expect pairs of columns, right? names(x5) <- c("monthyear", paste(rep(c("info", "n"), myseq), sep(1:myseq, each = 2), sep = ".")) library(zoo) x5$monthyear <- as.Date(as.yearmon(x5$monthyear, "%b %Y")) x5 # monthyear info.1 n.1 info.2 n.2 info.3 n.3 # 1 2001-01-01 Foo text 2 NA NA # 2 2006-11-01 Bar text 29 More bar text 4 Yet more bar text 102 # 3 2004-04-01 Further foo text 1 Combination foo and bar text 41 NA 
  7. 如果您真的想要長格式的數據,請使用reshape

     x6 <- reshape(x5, direction = "long", idvar = "monthyear", varying = 2:ncol(x5)) 
  8. 進行一些可選的清理,例如按日期對輸出進行排序,重置行名以及刪除不完整的情況:

     x6 <- x6[order(x6$monthyear), ] rownames(x6) <- NULL x6[complete.cases(x6), ] # monthyear time info n # 1 2001-01-01 1 Foo text 2 # 4 2004-04-01 1 Further foo text 1 # 5 2004-04-01 2 Combination foo and bar text 41 # 7 2006-11-01 1 Bar text 29 # 8 2006-11-01 2 More bar text 4 # 9 2006-11-01 3 Yet more bar text 102 

無論如何,請嘗試一下,然后根據需要進行修改。 我的猜測是,在某個時候,您必須在純文本編輯器中打開文件,並在其中進行一些初步的清理,然后才能繼續。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM