繁体   English   中英

R/Stringr 在第 n 次出现“_”后提取字符串并以第一次出现“_”结束

[英]R/Stringr Extract String after nth occurrence of "_" and end with first occurrence of "_"

使用 R 和 stringr package(或任何其他 package)

我想在第 n 次出现“_”后提取字符串,并以第一次出现“_”结束。

例如:

df <- c("J_J_HERE_jfdkaldjhieuwui","blahblah_ffd_THIS_fjdkalfj_jdka_")

我想要这个:

df_edited <- c("HERE","THIS")

或者对于这个例子,我想从“er”中提取一个空格后的所有内容,并以第一次出现的 _ 结尾:

df2 <- c("ex HERE_jfdkaldjhieuwui","ex_THIS_fjdkalfj_jdka_")

我想要这个:

df_edited <- c("HERE","THIS")

哪里有一个很好的备忘单来理解 stringr 条件,因为我很困惑。

我们可以创建一个基于“n”的模式

n <- 2
pat <- sprintf('([^_]+_){%d}([^_]+)_.*', n)
sub(pat, '\\2', df)
#[1] "HERE" "THIS"

细节 -

捕获一个或多个不是_ ( [^_]+ ) 的字符,后跟一个重复 'n' 次 (2) 的_ ,然后是下一组不是_ ( ([^_]+) ) 后跟一个_和其他字符。 在替换中,指定第二个捕获组的反向引用

您可以在分隔符上拆分数据,以便所有单词都可用。

df <- c("J_J_HERE_jfdkaldjhieuwui","blahblah_ffd_THIS_fjdkalfj_jdka_")
list_word <- strsplit(df, '_')
list_word

#[[1]]
#[1] "J"               "J"               "HERE"            "jfdkaldjhieuwui"

#[[2]]
#[1] "blahblah" "ffd"      "THIS"     "fjdkalfj" "jdka"    

然后您可以从列表中获取 position n处的任何值。

sapply(list_word, `[`, 3)
#[1] "HERE" "THIS"

sapply(list_word, `[`, 2)
#[1] "J"   "ffd"

另一种选择是识别字符串中元素的 position。 此解决方案在此处针对类似问题进行了复制。 这有点乱,但它实现了我想要的,并且会解决你的问题。 我也喜欢我可以修改它以适应各种情况。 尽管如果我能理解正则表达式,它无疑会更干净、更高效。

下面的代码使用了以下的组合; stringr::str_locate_all()输出列表列表,每个条目的矩阵 output 中的第一个“列”是模式每次出现的start 第二列是end值。 因此,每个嵌入矩阵的每一行都包含模式的开始和结束位置。

由于我在 dataframe 中工作并且想要使用特定的索引号,我发现最简单的方法是提取与模式开始相关的数字并将其保存为 dataframe 中的变量。

purrr::map()然后允许您提取特定值(在本例中为“n^th”)。我刚刚从每个值中提取了第二次出现(即第二行)的开始(即第一列)的索引矩阵.x[,1][2] ,在我的示例中)。 这个值然后需要是unlisted ,并存储为一个numeric

stringr::str_length()然后返回字符串的 integer 长度(或“字符总数”)。

提取出具体的索引值后,需要从 position 提取一个 substring 到 position。记住特殊字符需要正确escaped

最后, stringr::str_sub()提取特定模式第n'th次出现和字符串中最后一个字符之间的所有内容。

text_pattern <- "-"
df <- data.table(var_name = c("kj<hdf - fæld - adsk-jf -h af",
                              "kj<hds - sdaf - saflaf- adf",
                              "asdgya - oaid - aa-s--s a-",
                              "k<hdfk - lkja - ljad -"))

df <- df %>%
    mutate(second_dash = as.numeric(unlist
                                    (str_locate_all(pattern = text_pattern, var_name) %>%
                                            map(~ .x[,1][2])
                                        )
        )) %>%
    mutate(New_substring = str_sub(string = var_name, 
                                   start = second_dash+2, 
                                   end = str_length(var_name))) 

#                         var_name second_dash New_substring
# 1: kj<hdf - fæld - adsk-jf -h af          15 adsk-jf -h af
# 2:   kj<hds - sdaf - saflaf- adf          15   saflaf- adf
# 3:    asdgya - oaid - aa-s--s a-          15    aa-s--s a-
# 4:        k<hdfk - lkja - ljad -          15        ljad -

对于您的特定情况,继续使用破折号而不是下划线,您可以使用变量指定索引号(或出现次数),例如nm

在下面的工作示例中,我在开头添加了 2,并从子字符串的末尾减去 2 以删除空格。 还应注意,索引包括所讨论的字符。 因此,如果您不希望 output 中包含破折号“-”或下划线“_”,则需要从提取的索引中至少减去或添加 1。 一切都取决于您的具体目的。 这也可以通过删除值周围的空格“填充”来更智能地实现,但我只是包括修改以说明如何操作索引值。

text_pattern <- "-"
n = 2
m = n + 1

df <- data.table(var_name = c("kj<hdf - fæld - adsk-jf -h af",
                              "kj<hds - sdaf - saflaf- adf",
                              "asdgya - oaid - aa-s--s a-",
                              "k<hdfk - lkja - ljad -"))

df <- df %>%
    mutate(n_dash = as.numeric(unlist
                                    (str_locate_all(pattern = text_pattern, var_name) %>%
                                            map(~ .x[,1][n])
                                        )
        )) %>%
    mutate(m_dash = as.numeric(unlist
                                    (str_locate_all(pattern = text_pattern, var_name) %>%
                                            map(~ .x[,1][m])
                                        )
        )) %>%
    mutate(New_substring = str_sub(string = var_name, 
                                   start = n_dash+2, 
                                   end = m_dash-2))

#                         var_name New_substring n_dash m_dash
# 1: kj<hdf - fæld - adsk-jf -h af           ads     15     21
# 2:   kj<hds - sdaf - saflaf- adf         safla     15     23
# 3:    asdgya - oaid - aa-s--s a-             a     15     19
# 4:        k<hdfk - lkja - ljad -          ljad     15     22    

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM