Как мне контролировать количество элементов во вложенном списке? - PullRequest
1 голос
/ 12 февраля 2020

У меня есть функция l oop через веб-ссылки и извлечение соответствующих таблиц.

List.Of.Tabs <- map(pages2, ~ {

  name <- .x[1]
  link <- .x[2]
  Sys.sleep(2)
  webpage <- read_html(link)
  tbls <- html_nodes(webpage, "table")
  tbls_ls <- html_table(tbls, fill = TRUE)
  pos1 <- possibly(function(tbls) bind_rows(tbls) %>% 
                     filter_all(any_vars(. %in% c("Singapore", "SGP"))) %>%
                     mutate(name = name) 
                   , otherwise = NA)

  pos1(tbls_ls)
})

Однако в некоторых случаях я получал это сообщение:

Error in matrix(NA_character_, nrow = n, ncol = maxp) : 
  invalid 'ncol' value (too large or NA)
In addition: Warning messages:
1: In max(p) : no non-missing arguments to max; returning -Inf
2: In matrix(NA_character_, nrow = n, ncol = maxp) :
  NAs introduced by coercion to integer range

I полагал, что это связано с тем, что некоторые списки в pages2 содержат более 2 элементов.

print(pages2)

[[48]]
[1] "DICK'S SPORTING GOODS, INC. "                                                                  
[2] "https://www.sec.gov/Archives/edgar/data/1089063/000108906319000017/dks-exhibit_21x20190202.htm"

[[49]]
[1] "DIEBOLD NIXDORF, Inc "                                                                 
[2] "https://www.sec.gov/Archives/edgar/data/28823/000002882319000069/dbd12312018ex-211.htm"

[[50]]
[1] "DIGITAL REALTY TRUST, INC. "                                                               
[2] "https://www.sec.gov/Archives/edgar/data/1297996/000129799619000032/dlr10kex211_2018ss1.htm"
[3] "https://www.sec.gov/Archives/edgar/data/1297996/000129799619000032/dlr10kex212_2018ss1.htm"

Как я могу изменить свой код так, чтобы ошибка не появлялась?

1 Ответ

1 голос
/ 13 февраля 2020

Я не могу скопировать сообщения об ошибках с предоставленными ссылками. Но я могу пересмотреть ваш код. У вас есть списки с названием компании и URL-адресами. Поскольку вы указываете link <- .x[2], вы используете первый URL в каждом списке. Если вы организуете фрейм данных, вы можете решить эту проблему. Я создал фрейм данных на основе предоставленного вами объекта списка. В одном столбце есть названия компаний, а в другом - URL. map2_df() использует название компании и URL в каждой строке и очищает таблицы. Таким образом, вы можете убедиться, что у вас есть доступ ко всем имеющимся у вас URL.

library(rvest)
library(tidyverse) 

page2 <- list(c("DICK'S SPORTING GOODS, INC.", "https://www.sec.gov/Archives/edgar/data/1089063/000108906319000017/dks-exhibit_21x20190202.htm"),
              c("DIEBOLD NIXDORF, Inc", "https://www.sec.gov/Archives/edgar/data/28823/000002882319000069/dbd12312018ex-211.htm"),
              c("DIGITAL REALTY TRUST, INC.", "https://www.sec.gov/Archives/edgar/data/1297996/000129799619000032/dlr10kex211_2018ss1.htm", "https://www.sec.gov/Archives/edgar/data/1297996/000129799619000032/dlr10kex212_2018ss1.htm"))

# Create a data frame based on page2
map_dfr(.x = page2,
        .f = function(x){tibble(company = x[1],
                                url = grep(x = x, pattern = "https", value = TRUE))}) -> mytemp

# For each pair of company and url (for each row with company and url),
# scrape tables, bind lists, add a new column with a company name, and
# get rows that have Singapore or SGP

map2_df(.x = mytemp$url,
        .y = mytemp$company,
        .f = function(x, y){read_html(x) %>% 
                            html_nodes("table") %>% 
                            html_table(fill = TRUE) %>% 
                            bind_rows() %>% 
                            mutate(name = y)}) %>% 
filter_all(any_vars(. %in% c("Singapore", "SGP")))

   name                       X1                                      X2        X3        
   <chr>                      <chr>                                   <chr>     <chr>     
 1 DIEBOLD NIXDORF, Inc       Aisino Wincor Engineering Pte. Ltd.     Singapore 43.56%(71)
 2 DIEBOLD NIXDORF, Inc       Diebold Nixdorf Manufacturing Pte. Ltd. Singapore 94.72%(66)
 3 DIEBOLD NIXDORF, Inc       Diebold Nixdorf Singapore Pte. Ltd.     Singapore 94.72%(51)
 4 DIGITAL REALTY TRUST, INC. Digital Investment Management Pte. Ltd. NA        Singapore 
 5 DIGITAL REALTY TRUST, INC. Digital Japan 1 Pte. Ltd.               NA        Singapore 
 6 DIGITAL REALTY TRUST, INC. Digital Japan 2 Pte. Ltd.               NA        Singapore 
 7 DIGITAL REALTY TRUST, INC. Digital Japan Holding Pte. Ltd.         NA        Singapore 
 8 DIGITAL REALTY TRUST, INC. Digital Singapore 1 Pte. Ltd.           NA        Singapore 
 9 DIGITAL REALTY TRUST, INC. Digital Singapore 2 Pte. Ltd.           NA        Singapore 
10 DIGITAL REALTY TRUST, INC. Digital Singapore Jurong East Pte. Ltd. NA        Singapore 
11 DIGITAL REALTY TRUST, INC. Digital Investment Management Pte. Ltd. NA        Singapore 
12 DIGITAL REALTY TRUST, INC. Digital Japan 1 Pte. Ltd.               NA        Singapore 
13 DIGITAL REALTY TRUST, INC. Digital Japan 2 Pte. Ltd.               NA        Singapore 
14 DIGITAL REALTY TRUST, INC. Digital Japan Holding Pte. Ltd.         NA        Singapore 
15 DIGITAL REALTY TRUST, INC. Digital Singapore 1 Pte. Ltd.           NA        Singapore 
16 DIGITAL REALTY TRUST, INC. Digital Singapore 2 Pte. Ltd.           NA        Singapore 
17 DIGITAL REALTY TRUST, INC. Digital Singapore Jurong East Pte. Ltd. NA        Singapore 

БОНУС

Учитывая ваш комментарий, я думаю, что будет работать следующее. Обратите внимание, что у меня нет ваших реальных данных. Так что эта идея может / не может работать. Это лучшее, что я могу сделать.

map2_dfr(.x = mytemp$url,
         .y = mytemp$company,
         .f = function(x, y){read_html(x) %>% 
                 html_nodes("table") %>% 
                 html_table(fill = TRUE) %>% 
                 map(.f = ~mutate_all(., .funs = list(~as.character(.)))) %>% 
                 bind_rows() %>% 
                 mutate(name = y)}) %>% 
filter_all(any_vars(. %in% c("Singapore", "SGP")))
...