0

Webページから取得したテキスト形式のデータがあります。かなり長いですが、次の形式に従います。

<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

・・・でも、どうしたらいいのかわからない。text という文字ベクトルに html がある場合、stringr パッケージの関数を使用してmonthyearデータを抽出できます。

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

同じ方法でinfonデータを抽出できましたが、と年のエントリごとに複数のinfonエントリがあるため、それらを組み合わせる方法がわかりません。私はこれについてすべて間違っていますか?

4

1 に答える 1

2

残念ながら、データ ソースの品質を常に管理できるとは限らないため、面倒な手動処理に頼らざるを得ません。(データ アナリストの時間の大部分は、分析ではなくデータのクリーニングに費やされていると言う人もいます。)

コメントで既に述べたように、正規表現は 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指定された行に「月年」が見つかった場合、TRUEまたはを返します。「グループ」を作成し、文字ベクトルをリストに変換するためにFALSE使用します。cumsumsplit

    x3 <- split(x2, cumsum(grepl("monthyear", x2)))
    
  4. 必要に応じて、次の手順を複数の手順で実行できます。基本的な考え方はlapply、リストを上書きし、すべての HTML タグをタブに置き換え、ブラケットをタブに置き換えることです。その後、 を使用できますが、必要以上に多くのタブを挿入しているため、値read.delimがいっぱいの列が多数取得されることが予想されます。NA

    これは、いくつかの理由で失敗する可能性が最も高い場所です。(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」変数になり、他の列は info」と「n」になることがわかっているため、変数名を取得するためにいくつかの基本的なreps をラップすることができます。pasteそのas.yearmon過程で、「zoo」パッケージを使用して「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
    

とにかく試してみて、必要に応じて修正してください。私の推測では、ある時点でファイルをプレーン テキスト エディタで開き、先に進む前に予備的なクリーンアップを行う必要があると思います。

于 2013-01-24T07:50:37.857 に答える