Добавление значений из фрейма данных в список, созданный в цикле for

#r #for-loop #pdf #pdftools

Вопрос:

*Правка: Благодаря Мартину и небольшому количеству времени и внимания я смог получить код там, где мне это было нужно. Разве это некрасиво? Да, но это работает так, как мне сейчас полезно. Любые советы о том, как это исправить и сделать более эффективным, были бы очень полезны.

Используя фрейм данных trace_list , я пытаюсь добавить значения из Title и Year в выходные данные каждого списка в цикле for. Следующий код открывает ссылку PDF каждого штата на странице 10, извлекает данные о городах (которые варьируются от 1 до 12 городов). Очистите/приведите в порядок данные и сохраните их в списке, который будет привязан после сбора данных из каждого PDF-файла. Прямо сейчас он выводит только название города и числовое значение.

 data.frame(Link = c('https://www.atf.gov/file/146951/download','https://www.atf.gov/file/146966/download','https://www.atf.gov/file/146976/download','https://www.atf.gov/file/137041/download','https://www.atf.gov/file/137231/download','https://www.atf.gov/file/137301/download','https://www.atf.gov/docs/undefined/flwebsite17183911pdf/download','https://www.atf.gov/docs/undefined/kywebsite17183876pdf/download','https://www.atf.gov/docs/undefined/prwebsite17183917pdf/download'), Title = c('Alabama','California','District of Columbia','Alaska','Pennsylvania','Wyoming','Florida','Kentucky','Puerto Rico'), Year = c('2019','2019','2019','2018','2018','2018','2017','2017','2017'))
library(pdftools)
library(dplyr)
library(tabulizer)
library(english)
library(gsubfn)
library(rebus)
library(htmlwidgets)

citytrace <- list()
trace_list <- as.data.frame(trace_list)
for (i in seq_len(nrow(trace_list[c(1:159),]))) {
  pdf_link <- trace_list[i, 1]
  pdf_link <- paste0('',pdf_link,'')
  
  gpi_table <- tabulizer::extract_tables(pdf_link,output = "data.frame",pages = c(10, 10), area = list(c(230,0,280,717), c(275,0,321,725)),guess = F)
  
  city <- list(gpi_table)[[1]][[1]]
  #city <- city[!Reduce(`|`, lapply(city[1], grepl, pattern = '^[0-9] $""')),]
  city[city==""] <- NA
  city <- setNames(rbind(names(city), city), names(city))
  colnames(city) <- paste("V",seq(1,length(city),1),sep="")
  #city <- ifelse(city[1,]=='city',city[-1,],city)
  city <- if(length(city)>4){
    a <- data.frame(t(city))
    colnames(a) <- paste("X",seq(1,length(a),1),sep="")
    a[,1] <- factor(paste(a$X1,a$X2,a$X3,a$X4, sep = " "))
    a[,1] <- trimws(gsub("X|X\.[[:digit:]]|\.[[:digit:]]","",a$X1))
    a <- a[,-c(2:4)]
  } else {
    city %>%
      unite(city, 1:length(city), sep = " ", remove = FALSE) %>%
      mutate_all(na_if,"") %>%
      drop_na() %>%
      mutate(city = trimws(city), city = str_replace(city,"  "," ")) %>%
      select(city)
  }
  city <- ifelse(grepl(c("X|[[:digit:]]"),city),sapply(city, function(x) gsub(c('"*"|[[:digit:]] |X|,|\.|^c\(|\)$|'),"",x)),sapply(city, function(x) gsub("\."," ",x)))
  city <- unique(data.frame(matrix(unlist(city), nrow=length(city), byrow=TRUE)))
  city[which(city=="" | city=="NA"),] <- NA
  city <- city[complete.cases(city), , drop=FALSE]
  colnames(city) <- "city"
  
  count <- list(gpi_table)[[1]][[2]]
  count <- setNames(rbind(names(count), count), names(count))
  colnames(count) <- paste("V",seq(1,length(count),1),sep="")
  count <- ifelse(grepl("^X[[:digit:]] $|^X[[:digit:]] \.[[:digit:]] $",count),sapply(count,function(x) gsub("X|\.[[:digit:]]$","",x)),count)
  count <- cbind(city,count)
  
  library(english)
  library(gsubfn)
  result <- pdf_text(pdf_link)[10]  %>%
    str_split("n") %>%
    first() %>%
    as_tibble() %>%
    mutate_all(list(~na_if(.,""))) %>%
    filter(grepl("NOTE:|determined",value))
  x3 <- ifelse(is.na(result[2,]),paste(result[1,], result[2,], sep=". "),paste(result[1,], result[2,], sep=" "))
  x3 <- dplyr::tibble(line = 1, text = x3)
  sv <- strsplit(x3$text, split = "\. ")
  x3 <- data.frame(V1 = rep(x3$line, sapply(sv, length)), V2 = unlist(sv))
  x3[1,2] <- gsubfn("\w ", setNames(as.list(1:10), as.english(1:10)), x3[1,2])
  x3[2,2] <- gsubfn("\w ", setNames(as.list(1:10), as.english(1:10)), x3[2,2])
  x3$V2 <- gsub(",","",x3$V2)
  x3$V2 <- gsub("NA",0,x3$V2)
  x3$city <- ifelse(grepl("additional",x3$V2),"Other","None")
  
  library(rebus)
  library(htmlwidgets)
  trcount <- DGT %R% optional(DGT) %R% optional(DGT) %R% optional(DGT) %R% optional(DGT)
  str_view_all(x3$V2, 
               pattern = trcount)
  a0 <- str_match_all(x3$V2, pattern = trcount)
  a0[[1]] <- a0[[1]][-1,1]
  x3$count <- unlist(a0)
  x4 <- as.data.frame(x3[,-c(1:2)])
  x5 <- rbind(count,x4)
  
  x5 <- x5 %>% 
    mutate(state = trace_list[i, 2],
           year  = trace_list[i, 3]) 
  citytrace[[i]] <- x5
}
citytrace <- do.call(rbind,citytrace)
citytrace$city <- gsub(c(' NA|  '), '', citytrace$city)
citytrace$count <- gsub(c('\.'), '', citytrace$count)
print(citytrace)
 

С чем у меня возникли проблемы, так это с присвоением значений «Название» и «Год» из «списка трассировки» циклическому выходу. Ожидаемые результаты ниже:

город считать государство год
Бирмингем 100 Алабама 2019
Фэрбенкс 10 Аляска 2018

Я не совсем уверен, как начать это делать, и искал помощи в этом. Мы будем очень признательны за любые советы о том, как очистить код.

Комментарии:

1. (1) Здесь много кода. Действительно ли это минимальный воспроизводимый пример? (2) Вы должны поместить library(...) инструкции поверх своего кода. Внутри a for -цикла их трудно обнаружить, и вы (не хотите) загружать их несколько раз.

2. Исправлено 2. Что вам нужно для воспроизводимого примера? 10?

3. Я не могу запустить ваш код, но я думаю, что вашей проблеме не нужен весь показанный код. Если я правильно понимаю, у вас есть вывод в какой-то форме, и вы просто хотите добавить информацию о состоянии и годе. Таким образом, в основном вам нужно показать выходные данные, источник состояния/года (список трассировки) и желаемый результат.

4. Вот именно так.

5. Как выглядит x5 в конце for цикла?

Ответ №1:

Поскольку я не могу запустить ваш код здесь, небольшое предложение для вашего кода

 library(dplyr)

for (i in seq_len(nrow(trace_list))) {
  pdf_link <- trace_list[i, 1]
  # Do stuff with the URL
  # probably you don't need the inner for-loop
  # create the data.frame x5
  
  x5 %>% 
    mutate(state = trace_list[i, 2],
           year  = trace_list[i, 3]) 
}
 

Некоторые замечания:

  • Я не понимаю определения вашего for цикла: повторение list(trace_list[c(1:2),]) для меня не имеет никакого смысла.
  • Извлечение и хранение url pdf_link данных лучше выполнять с помощью pdf_link <- trace_list[i, 1] .
  • Повторение unlist(pdf_link) также не имеет смысла для меня. Я думаю , вы можете использовать trace_list[i, 1] trace_list[i, 2] или trace_list[i, 3] вместо этого.

Комментарии:

1. Для вашего первого замечания: я выбирал только первые две строки, чтобы проверить данные. Я исправил это сейчас, но это была моя ошибка, что я включил его туда. Поэтому, когда я запустил tabulizer::extract_tables, я получил сообщение об ошибке. В основном это был только выбор первой ссылки для запуска функции. Я посмотрел в Интернете и понял, что столбец для URL-адресов должен быть векторным. Я не знаю, как объяснить, кроме того, что функция работает сейчас.