我有帶有“鏡像”分隔符的語音轉錄,即成對的符號分別標記開始和結束,例如(and)或<and >。此資料中的分隔符是方括號:
df <- data.frame(
id = 1:9,
Utterance = c("[but if I came !ho!me", # <- closing square bracket is missing
"=[ye::a:h]", # OK!
"=[yeah] I mean [does it", # <- closing square bracket is missing
"bu[t if (.) you know", # <- closing square bracket is missing
"=ye::a:h]", # <- opening square bracket is missing
"[that's right] YEAH (laughs)] [ye::a:h]", # <- opening square bracket is missing
"cos I've [heard] very sketchy stories", # OK!
"[cos] I've [heard very sketchy [stories]", # <- closing square bracket is missing
"oh well] that's great" # <- opening square bracket is missing
))
我想過濾那些缺少至少一個開頭或至少一個結尾分隔符的行(因為這表示轉錄錯誤)。我實際上用這種str_count方法做得很好:
library(string)
library(dplyr)
df %>%
filter(str_count(Utterance, "\\[|\\]") %in% c(1,3,5,7,9))
id Utterance
1 1 [but if I came !ho!me
2 3 =[yeah] I mean [does it
3 4 bu[t if (.) you know
4 5 =ye::a:h]
5 6 [that's right] YEAH (laughs)] [ye::a:h]
6 8 [cos] I've [heard very sketchy [stories]
7 9 oh well] that's great
但想知道是否可以設計正則運算式來直接檢測缺少元素的字串。我一直在嘗試這個正則運算式,因為缺少右括號:
p_op <- "(?<!.{0,10}\\[.{0,10})\\].*$"
df %>%
filter(str_detect(Utterance, p_op))
效果很好,這適用于缺少右括號,它不會捕獲所有匹配項:
p_cl<- "\\[(?!.*\\]).*$"
df %>%
filter(str_detect(Utterance, p_cl))
如何更好地制定模式或模式?
uj5u.com熱心網友回復:
我們可以使用with 2而不是%in%向量%%
library(dplyr)
library(stringr)
df %>%
filter(as.logical(str_count(Utterance, "\\[|\\]")%% 2))
-輸出
id Utterance
1 1 [but if I came !ho!me
2 3 =[yeah] I mean [does it
3 4 bu[t if (.) you know
4 5 =ye::a:h]
5 6 [that's right] YEAH (laughs)] [ye::a:h]
6 8 [cos] I've [heard very sketchy [stories]
7 9 oh well] that's great
或者可以在中使用模式 ( \\[[^\\]] (\\[|$)|(^|\\])[^\\[] \\])str_detect
df %>%
filter(str_detect(Utterance, "\\[[^\\]] (\\[|$)|(^|\\])[^\\[] \\]"))
id Utterance
1 1 [but if I came !ho!me
2 3 =[yeah] I mean [does it
3 4 bu[t if (.) you know
4 5 =ye::a:h]
5 6 [that's right] YEAH (laughs)] [ye::a:h]
6 8 [cos] I've [heard very sketchy [stories]
7 9 oh well] that's great
在這里,我們檢查一個左括號[后跟一個或多個字符,而不是]一個[或字串結尾 ( $) 或右括號的類似模式
uj5u.com熱心網友回復:
另一種可能的解決方案,使用purrr::map_dfr.
解釋
按照@ChrisRuehlemann 的要求,我在下文中提供了對我的解決方案的解釋:
使用,我們將每個話語的所有和
str_extract_all(df$Utterance, "\\[|\\]")提取為一個串列,并根據它們在話語中出現的順序。[]我們迭代之前為話語創建的所有串列。但是,我們有一個方括號串列。因此,我們需要事先將串列折疊成一串方括號 (
str_c(.x, collapse = ""))。我們將每個話語的方括號字串與如下字串
[][][]...(str_c(rep("[]", length(.x)/2), collapse = "")) 進行比較。如果這兩個字串不相等,則缺少方括號!完成
map_dfr后,我們會得到一列TRUEandFALSE,我們可以使用它來根據需要過濾原始資料框。
library(tidyverse)
str_extract_all(df$Utterance, "\\[|\\]") %>%
map_dfr(~ list(OK = str_c(.x, collapse = "") !=
str_c(rep("[]", length(.x)/2), collapse = ""))) %>%
filter(df,.)
#> id Utterance
#> 1 1 [but if I came !ho!me
#> 2 3 =[yeah] I mean [does it
#> 3 4 bu[t if (.) you know
#> 4 5 =ye::a:h]
#> 5 6 [that's right] YEAH (laughs)] [ye::a:h]
#> 6 8 [cos] I've [heard very sketchy [stories]
#> 7 9 oh well] that's great
uj5u.com熱心網友回復:
如果您需要一個函式來驗證(嵌套)括號,這里有一個基于堆疊的函式。
valid_delim <- function(x, delim = c(open = "[", close = "]"), max_stack_size = 10L){
f <- function(x, delim, max_stack_size){
if(is.null(names(delim))) {
names(delim) <- c("open", "close")
}
if(nchar(x) > 0L){
valid <- TRUE
stack <- character(max_stack_size)
i_stack <- 0L
y <- unlist(strsplit(x, ""))
for(i in seq_along(y)){
if(y[i] == delim["open"]){
i_stack <- i_stack 1L
stack[i_stack] <- delim["close"]
} else if(y[i] == delim["close"]) {
valid <- (stack[i_stack] == delim["close"]) && (i_stack > 0L)
if(valid)
i_stack <- i_stack - 1L
else break
}
}
valid && (i_stack == 0L)
} else NULL
}
x <- as.character(x)
y <- sapply(x, f, delim = delim, max_stack_size = max_stack_size)
unname(y)
}
library(dplyr)
valid_delim(df$Utterance)
#[1] FALSE TRUE FALSE FALSE FALSE FALSE TRUE FALSE FALSE
df %>% filter(valid_delim(Utterance))
# id Utterance
#1 2 =[ye::a:h]
#2 7 cos I've [heard] very sketchy stories
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/418390.html
標籤:
