【问题标题】:Splitting and classifying txt lines into a table将txt行拆分和分类成表格
【发布时间】:2021-09-28 05:59:10
【问题描述】:

我有一个很长的 word 文档,其中列出了这样的项目:

  1. 项目 1
    • entry1
    • 条目2
    • 条目3
  2. 项目 2
    • entry1
    • 条目2
    • 条目3
  3. (等等...)

item是物种名称,entry是对应的位置和日期信息,不过现在已经不重要了。

我正在尝试将这个极长的文档放入 R 中的一个合理的 table/tibble 对象中,我的想法是使用它:

library (stringr)
data <- readLines("data.txt")
test_data <- str_sub(data, 1, 3)

然后用“数据”的每个元素的“项目”身份分配另一个向量(即每个日期+位置对应的物种)。我试图为此使用for循环并测试每行是否以“”开头,但我被卡住了。

results <- vector (length = length(data))
   for (i in 1:length(data)) {
   if (test_data[i] != "   ") {
      results[i] = data[i]
   } else {
        while #here I am stuck

谢谢

【问题讨论】:

  • 嗨 :) 你总是每件作品有 3 个条目吗?
  • 嗨!不,条目的数量变化很大。
  • 格式是否总是像,对于项目,(整数).Item 和对于条目,(空格或制表符)条目?
  • 是的,每个项目都直接以字母开头(二项式物种名称,例如智人)。然后每个条目以十二个空格“”开头,然后是单词(位置名称,然后是同一行中的日期信息)。
  • 请提供足够的代码,以便其他人更好地理解或重现问题。

标签: r text data-wrangling


【解决方案1】:

我想我有一些事情要开始了。这个想法是将您的文本文件加载为单个长字符串,然后将其分解为对应于 Item + 条目的片段并将其存储在列表中。最后,在列表中使用lapply 分隔Item 和条目。

filename <- "test.txt"
# read your file a single long string
step1 <- readChar(filename, file.info(filename)$size)
# find the pattern that separate each Item (from a copy/paste of the example it is "\r\n\r\n") and make a list of items
# with associated entries
step2 <- as.list(unlist(strsplit(step1, split = "\r\n\r\n")))
# lastly split the vectors from step2
step3 <- lapply(step2, function(x) unlist(strsplit(x, split = "\r\n    ")))

输出:

> step3
[[1]]
[1] "Item 1" "entry1" "entry2" "entry3"

[[2]]
[1] "Item 2" "entry1" "entry2" "entry3"

您可以从这里开始使用“常用”工具来清理和组织数据例如

df <- as.data.frame(do.call(rbind, step3))
df <- tidyr::pivot_longer(df, 2:ncol(df))
df <- df[, -2]
names(df) <- c("Items", "Entries")
df
# A tibble: 6 x 2
  Items  Entries
  <chr>  <chr>  
1 Item 1 entry1 
2 Item 1 entry2 
3 Item 1 entry3 
4 Item 2 entry1 
5 Item 2 entry2 
6 Item 2 entry3 

【讨论】:

  • 谢谢!这非常有用
【解决方案2】:

这是基于“每个条目以十二个空格开头”这一事实的 tidyverse 方法。

# fake data
obj <- c("Item 1",
"            entry1",
"            entry2",
"            entry3",
"            entry4",
"Item 2",
"            entry1",
"            entry2",
"            entry3"
)

writeLines(obj, con = "data2.txt")


# read in and convert
library(tidyverse)

dat <- readLines("data.txt", skipNul = TRUE)

dat |>
  enframe() |>
  separate(
    value,
    into = c("item", "entry"),
    sep = "\\s{12}",
    convert = TRUE,
    fill = "right"
  ) |>
  mutate(item = na_if(item, "")) |>
  fill(item, .direction = "down") |>
  filter(!(is.na(entry)))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-17
    • 1970-01-01
    相关资源
    最近更新 更多