/ / Tworzenie ramki danych ze skrobanego wektora znaków - r, web-scraping, html-parsing, rvest

Tworzenie ramki danych ze skrobanego wektora znaków - r, web scraping, html-parsing, rvest

Próbuję utworzyć ramkę danych, która ma kolumny: imię, nazwisko, przyjęcie, stan, identyfikator członka. Oto mój kod

library("rvest")

candidate_url <- "https://www.congress.gov/help/field-values/member-bioguide-ids"
candidate_page <- read_html(candidate_url)
candidate_nodes <- html_nodes(candidate_page, "table")
candidate_list <- html_text(candidate_nodes)

Moim głównym problemem jest uzyskanie identyfikatorów członków. Przykładowy identyfikator to A000009. Kiedy używam gsub funkcja tracę wiodącą literę A w tym przykładzie. A pochodzi od nazwiska kandydata (Abercrombie), ale nie wiem, jak dodać A z powrotem do ID członka, oczywiście jeśli jest lepszy sposób, jestem otwarty na wszelkie sugestie.

Odpowiedzi:

1 dla odpowiedzi № 1

Ponieważ masz tabelę HTML, użyj html_table wyodrębnić go do data.frame. Będziesz potrzebował fill = TRUE, ponieważ w tabeli znajdują się dodatkowe puste wiersze wstawione między każdą pozycją, którą można później łatwo upuścić tidyr::drop_na.

library(tidyverse)
library(rvest)

page <- "https://www.congress.gov/help/field-values/member-bioguide-ids" %>%
read_html()

members <- page %>%
html_node("table") %>%
html_table(fill = TRUE) %>%
set_names("member", "bioguide") %>%
drop_na(member) %>%    # remove empty rows inserted in the table
tbl_df()    # for printing

members
#> # A tibble: 2,243 x 2
#>                                             member bioguide
#>  *                                           <chr>    <chr>
#>  1       Abdnor, James (Republican - South Dakota)  A000009
#>  2         Abercrombie, Neil (Democratic - Hawaii)  A000014
#>  3     Abourezk, James (Democratic - South Dakota)  A000017
#>  4     Abraham, Ralph Lee (Republican - Louisiana)  A000374
#>  5        Abraham, Spencer (Republican - Michigan)  A000355
#>  6         Abzug, Bella S. (Democratic - New York)  A000018
#>  7 Acevedo-Vila, Anibal (Democratic - Puerto Rico)  A000359
#>  8       Ackerman, Gary L. (Democratic - New York)  A000022
#>  9    Adams, Alma S. (Democratic - North Carolina)  A000370
#> 10          Adams, Brock (Democratic - Washington)  A000031
#> # ... with 2,233 more rows

The member kolumna może zostać dalej wydobyta, jeśli chcesz.

Istnieje również wiele innych przydatnych źródeł dla tych danych, z których niektóre korelują z innymi użytecznymi zmiennymi. Ten jest dobrze skonstruowany i regularnie aktualizowany.


1 dla odpowiedzi nr 2

Wypróbuj to. Zaktualizowałem to, aby uwzględnić oddzielenie różnych pól.

library("rvest")
library("dplyr")
library("tidyr")

candidate_url <- "https://www.congress.gov/help/field-values/member-bioguide-ids"
candidate_page <- read_html(candidate_url)
candidate_nodes <- html_nodes(candidate_page, "table")
df.candidates <- as.data.frame(html_table(candidate_nodes, header = TRUE, fill = TRUE), stringsAsFactors = FALSE)
df.candidates <- df.candidates[!is.na(df.candidates$Member),]

df.candidates <- df.candidates %>%
mutate(Party.State = gsub("[\(\)]", "", regmatches(Member, gregexpr("\(.*?\)", Member))[[1]])) %>%
separate(Party.State, into = c("Party","State"), sep = " - ") %>%
mutate(Full.name = trimws(regmatches(df.candidates$Member, regexpr("^[^\(]+", df.candidates$Member)))) %>%
separate(Full.name, into = c("Last.Name","First.Name","Suffix"), sep = ",", fill = "right") %>%
select(First.Name, Last.Name, Suffix, Party, State, Member.ID)

0 dla odpowiedzi № 3

To jest trochę hackish, ale jeśli chcesz wyodrębnić zmienne za pomocą regex tutaj kilka wskazówek.

candidate_list <- unlist(candidate_list)

ID <- regmatches(candidate_list,
gregexpr("[a-zA-Z]{1}[0-9]{6}", candidate_list))

party_state <- regmatches(candidate_list,
gregexpr("(?<=\()[^)]+(?=\))", candidate_list, perl=TRUE))

names_etc <- strsplit(candidate_list, "[a-zA-Z]{1}[0-9]{6}")

names <- sapply(names_etc, function(x) sub(" \([^)]*\)", "", x))