使用 r 中的 dplyr 将纯文本转换为数据框

converting plain text to data frame using dplyr in r

我正在尝试使用 r 将使用 pdftools 和 tidyverse 从 pdf 抓取的纯文本转换为数据框。我希望有一个使用 tidyverse 包的解决方案。我使用以下代码获取包含我的基本信息的字符串列表:

library(tidyverse)
library(pdftools)

textdf <- pdf_text("raw pdf.pdf")

all_stats_lines <- textdf[3:28]%>%
  str_squish()%>%
  str_replace_all(",", "")%>%
  str_remove_all("\+80% \+80% \+80% \+40% \+40% \+40% Baseline Baseline Baseline \-40% \-40% 
  \-40% \-80% \-80% \-80% Sun Feb 16 Sun Mar 8 Sun Mar 29 Sun Feb 16 Sun Mar 8 Sun Mar 29 Sun Feb 
  16 Sun Mar 8 Sun Mar 29")%>% 
  str_remove_all("compared to baseline")%>%
  strsplit("   ")



这会产生以下 26 个字符串列表,格式如下:


[[1]]
[1] "Alaska Variable 1 Variable 2 Variable 3 42  15  5" 
[2] "Variable 4 Variable 5 Variable 6 43  30  11"              
[3] "Alabama Variable 1 Variable 2 Variable 3 27  9  79"
[4] "Variable 4  Variable 5 Variable 6 20  23  4  "          

[[2]]
[1] "Arizona Variable 1 Variable 2 Variable 3 40  17  7" 
[2] "Variable 4 Variable 5 Variable 6 41  33  10"              
[3] "Arkansas Variable 1 Variable 2 Variable 3 29  7  81"
[4] "Variable 4  Variable 5 Variable 6 22  27  7  "   

... etc.

注意子列表第 1 行和第 3 行开头的状态名称以及变量名称中的空格。每个状态应该是一行。应该有 6 列变量 1 变量 2 变量 3 变量 4 变量 5 变量 6 并依次对应相应的值。

关于如何构建这个 table 的任何解决方案?

要执行此操作,您需要解决几个问题。

  1. 将文本拆分为多列
  2. 组合行对
  3. 组合列表

如果您只打算这样做一次,那么将您的数据复制到 Excel 中,在那里格式化,然后将其加载到 R 中可能会更简单。但是如果您致力于使用 R,然后我们需要按顺序完成每一个:

1) 文本到列

strsplit(string, " ") 将在 space 上拆分文本字符串。 strsplit(string, "[[:space:]]+") 将在白色 space 上拆分,将连续的白色 space 视为单个拆分。但是,您要避免将 "Variable 1" 分隔为 "Variable" 和“1”,并将 "North Dakota" 分隔为 "North" 和 "Dakota"

此处的一个快速解决方案是 gsub("North ", "North_", string),它将 "North Dakota" 变成 "North_Dakota",因此当您应用 strsplit.

时,这两个词会保持在一起

2) 组合行对

您可以使用取模来提取向量的每个第二个条目:1:4 %% 2 将 return c(1,0,1,0)。这可用于提取每隔一个值,如下所示:vec[1:4 %% 2 == 1].

将它们成对组合可以得到如下结果:

vec = c('a', 'b', 'c', 'd')
paste(vec[1:4 %% 2 == 1], vec[1:4 %% 2 == 0])

3) 组合列表

这里最简单的解决方案可能是 unlist。但是您也可以使用 purrr 包中的 reduce 函数。

全部结合起来

data = unlist(data)
data = trimws(data)
nn = length(data)
data = paste(data[1:nn %% 2 == 1], data[1:nn %% 2 == 0])

# add other rules here for state names that are two words
data = gsub("ariable ", "ariable_", data)
data = gsub("North ", "North_", data)

data %>%
  strsplit("[[:space:]]+") %>%
  purrr::reduce(rbind) %>%
  as.data.frame()