嗨,我还没有看到一个类似的解决方案,我有这个问题。我正在尝试创建一个regrex模式,以提取{}中的主题词后面的字符,并将它们放在一个主要列中。但是,主题词在第2行中重复,我需要提取并组合后面两个{}中的所有字符。理想情况下,我也会为次要的和偶然的属性这样做。我不知道我在这里做错了什么。谢谢!
test <- data.frame(lith=c("major{basalt} minor{andesite} incidental{dacite rhyolite}",
"major {andesite flows} major {dacite flows}",
"major{andesite} minor{dacite}",
"major{basaltic andesitebasalt}"))
test %>%
mutate(major = str_extract_all(test$lith, "[major].*[{](\\D[a-z]*)[}]") %>%
map_chr(toString))我想要的是:
major minor incidental
1 basalt andesite dacite ryolite
2 andesite flows, decite flows <NA> <NA>
3 basaltic andesitebasalt <NA> <NA>发布于 2022-07-15 12:26:24
首先,(几乎)永远不要在以test$开头的dplyr管道中使用test %>%。充其量,它只是有点低效;如果有任何中间步骤重新排序、修改或过滤数据,那么结果要么是(a)错误,首选;要么(b)静默错误。理由是:假设你知道
test %>%
filter(grepl("[wy]", lith)) %>%
mutate(major = str_extract_all(test$lith, ...))在这种情况下,filter将数据从4行减少到只有2行。但是,由于您使用的是test$lith,这是在管道启动之前从test的内容中提取的,所以这里的test$lith是长度-4,在这里我们需要它的长度-2。
或者(和优先考虑),
test %>%
filter(grepl("[wy]", lith)) %>%
mutate(major = str_extract_all(lith, ...))在这里,str_extract_all(lith, ...)只看到两个值,而不是原始的四个。
有规律的回答.
我将添加一个行号rn列作为原始行引用(源的id)。这是两种功能(对于内部工作而言),如果您需要将它与原始数据绑定起来的话。我推断,您将这些值分组为字符串而不是列表列,但如果需要,很容易切换到后者。
library(dplyr)
library(stringr) # str_extract_all
library(tidyr) # unnest, pivot_wider
test %>%
mutate(
rn = row_number(),
tmp = str_extract_all(lith, "\\b([[:alpha:]]+) ?\\{([^}]+)\\}"),
tmp = lapply(tmp, function(z) strcapture("^([^{}]*) ?\\{(.*)\\}", z, list(categ="", val="")))
) %>%
unnest(tmp) %>%
mutate(across(c(categ, val), trimws)) %>%
group_by(rn, categ) %>%
summarize(val = paste(val, collapse = ", ")) %>%
pivot_wider(rn, names_from = "categ", values_from = "val") %>%
ungroup()
# # A tibble: 4 x 4
# rn incidental major minor
# <int> <chr> <chr> <chr>
# 1 1 dacite rhyolite basalt andesite
# 2 2 NA andesite flows, dacite flows NA
# 3 3 NA andesite dacite
# 4 4 NA basaltic andesitebasalt NA https://stackoverflow.com/questions/72983571
复制相似问题