首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >即使字符串的顺序不同,Stringr正则表达式也可以工作。

即使字符串的顺序不同,Stringr正则表达式也可以工作。
EN

Stack Overflow用户
提问于 2021-09-22 22:34:25
回答 2查看 72关注 0票数 1

为在实际数据中增加复杂性而编辑的,请参阅下面。同时,我也接受了一个基于我最初是如何问这个问题的答案。,我试着看了其他几个可用的Q/A,但我看的那些似乎都不适合我,/或者没有足够的细节让我理解如何实现这些解决方案。我不太习惯使用regex,所以我很难想出一个模式。我有多个文本字符串,其中一些可以在数据中组合,这些组合的字符串可以按任意顺序放置。这是一个很长的数据集,对于在数据框架内创建的多个列,我必须重复一个类似的过程,其内容部分基于str_detect函数的真/假,因此效率是相当重要的。

同样重要的是,正如我在其他答案中提到的那样,我对Python/Perl一无所知。我在RStudio工作。

首先,一个与我的数据类似且更简单的数据框架。

代码语言:javascript
运行
复制
SN <- c(1001, 1002, 1003, 1004)
fwd_fender <- c(1, 0, 1, 1)
note <- c("FWD FNDR DMG", 
          "MID BODY CHASS DMG", 
          "FWD FNDR EXCESS WEAR, MID BODY CHASS DMG", 
          "MID BODY CHASS DMG, FWD FNDR PAINT SCRATCH")
df <- data.frame(SN, fwd_fender, note)

产生了这一数据框架:

代码语言:javascript
运行
复制
SN fwd_fender                                       note
1 1001          1                               FWD FNDR DMG
2 1002          0                         MID BODY CHASS DMG
3 1003          1   FWD FNDR EXCESS WEAR, MID BODY CHASS DMG
4 1004          1 MID BODY CHASS DMG, FWD FNDR PAINT SCRATCH

基本上,我需要做的是创建另一列,我们称之为fwd_fender_mech_dmg,在那里我可以根据note列重新编码观察结果。在本例中,"FWD FNDR DMG“和"FWD FNDR超额磨损”都算作"fwd_fender_mechanical_dmg“。其他的音符没有。因此,我希望最终生成如下所示的数据框架:

代码语言:javascript
运行
复制
SN fwd_fender                                       note fwd_fender_mech_dmg
1 1001          1                               FWD FNDR DMG                   1
2 1002          0                         MID BODY CHASS DMG                   0
3 1003          1   FWD FNDR EXCESS WEAR, MID BODY CHASS DMG                   1
4 1004          1 MID BODY CHASS DMG, FWD FNDR PAINT SCRATCH                   0

我有很多列,有很多不同的变量,所以我试图尽可能多地使用regex (理想情况下),以提高编码的效率,但我没有让它很好地工作。

这是一个基本的测试序列和模式。

代码语言:javascript
运行
复制
yes <- c("FWD FNDR DMG", "FWD FENDER EXCESS WEAR")
no <- c("MID BODY CHASS DMG", "FWD FNDR PAINT SCRATCH")
maybe <- c("FWD FNDR EXCESS WEAR, MID BODY CHASS DMG", "MID BODY CHASS DMG, FWD FNDR PAINT SCRATCH") 
s <- c(yes, no, maybe)
pattern <- "FE?ND.*(WEAR|DMG)"
str_detect(s,pattern,negate = FALSE)

其结果如下:

代码语言:javascript
运行
复制
[1]  TRUE  TRUE FALSE FALSE  TRUE FALSE

这是一个预期的结果,但是请注意,如果我切换了maybe中最后两个条目的顺序,代码就会产生不正确的结果。

代码语言:javascript
运行
复制
yes <- c("FWD FNDR DMG", "FWD FENDER EXCESS WEAR")
no <- c("MID BODY CHASS DMG", "FWD FNDR PAINT SCRATCH")
maybe <- c("FWD FNDR EXCESS WEAR, MID BODY CHASS DMG", "FWD FNDR PAINT SCRATCH, MID BODY CHASS DMG") #Last Entry Reversed
s <- c(yes, no, maybe)
pattern <- "FE?ND.*(WEAR|DMG)"
str_detect(s,pattern,negate = FALSE)

它产生了这样的结果:

代码语言:javascript
运行
复制
[1]  TRUE  TRUE FALSE FALSE  TRUE  TRUE

那么,有什么想法可以让我做这件事吗?

谢谢!

编辑

我的真实数据比最初的简化版本更复杂,所以这里有一个数据框架,它更接近于反映我的数据。

代码语言:javascript
运行
复制
SN <- c(1001, 1002, 1003, 1004)
fwd_fender <- c(1, 0, 1, 1)
fwd_fender_note <- c("FWD FNDR DMG", 
          "MID BODY CHASS DMG", 
          "FWD FNDR EXCESS WEAR, MID BODY CHASS DMG", 
          "MID BODY CHASS DMG, FWD FNDR PAINT SCRATCH")
rear_axel <- c(0, 1, 1, 1)
rear_axel_note <- c("#", "CORROSION", "CORR, CRACK", "CRACK, WEAR")
computer <- c(0, 1, 0, 0)
computer_note <- c("PROGRAM BUG", "ELEC FAULT", "#", "#")
mid_body_chass <- c(1, 1, 0, 1)
mid_body_chass_note <- c("MID BODY CHASS DMG", "WEAR", "#", "CORR")
df <- data.frame(SN, fwd_fender, fwd_fender_note, rear_axel, rear_axel_note, computer, computer_note, mid_body_chass, mid_body_chass_note)

它产生这个数据框架:

代码语言:javascript
运行
复制
 SN fwd_fender                            fwd_fender_note rear_axel rear_axel_note computer computer_note mid_body_chass
1 1001          1                               FWD FNDR DMG         0              #        0   PROGRAM BUG              1
2 1002          0                         MID BODY CHASS DMG         1      CORROSION        1    ELEC FAULT              1
3 1003          1   FWD FNDR EXCESS WEAR, MID BODY CHASS DMG         1    CORR, CRACK        0             #              0
4 1004          1 MID BODY CHASS DMG, FWD FNDR PAINT SCRATCH         1    CRACK, WEAR        0             #              1
  mid_body_chass_note
1  MID BODY CHASS DMG
2                WEAR
3                   #
4                CORR

磨损和裂纹都算作“机械损伤”,因此即使它们是单独的观察,在fwd_fender_mech_dmg列中它们也只应被算作1(只识别某一类型观察的存在与否,而不是有多少)。在这个分析中没有特别跟踪一些观察结果,所以“程序错误”应该是0。

因此,我最终想要达到的是一个数据框架,它看起来有点像以下所示:

代码语言:javascript
运行
复制
rear_axel_corrosion <- c(0, 1, 1, 0)
computer_electrical <- c(0, 1, 0, 0)
mid_body_chass_mech_dmg <- c(1, 1, 1, 1)
df2 <- data.frame(SN, fwd_fender_mech_dmg, rear_axel_mech_dmg, rear_axel_corrosion, computer_electrical, mid_body_chass_mech_dmg)

df2
 SN fwd_fender_mech_dmg rear_axel_mech_dmg rear_axel_corrosion computer_electrical mid_body_chass_mech_dmg
1 1001                   1                  0                   0                   0                       1
2 1002                   0                  0                   1                   1                       1
3 1003                   1                  1                   1                   0                       1
4 1004                   0                  1                   0                   0                       1

还要注意的是,有时操作者输入错误的插槽(因此,在"fwd_fender_note“下的”中体小妞DMG“,这意味着实际上应该有一个1在该行的中体底盘损坏。

哇,我知道那是很多,希望我没有把它弄得太复杂。谢谢!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-09-23 00:47:18

代码的问题是,您将'xxx,yyy‘作为两个字符元素(就像字符向量中的那样),但实际上它是一个两个单词的字符标量。

如果我们希望当前正则表达式能够工作,我们可以首先通过逗号对字符串进行str_split,然后对所有子字符串调用str_detect,最后,将输出转换为每行一个逻辑。

代码语言:javascript
运行
复制
library(stringr)
library(purrr)
library(dplyr)

df %>% mutate(fwd_fender_mech_dmg= str_split(note, ',') %>%
                      map(~str_detect(.x, "FE?ND.*(WEAR|DMG)")%>%
                      reduce(`|`)))
    SN fwd_fender                                       note fwd_fender_mech_dmg
1 1001          1                               FWD FNDR DMG                   1
2 1002          0                         MID BODY CHASS DMG                   0
3 1003          1   FWD FNDR EXCESS WEAR, MID BODY CHASS DMG                   1
4 1004          1 MID BODY CHASS DMG, FWD FNDR PAINT SCRATCH                   0

这与昏迷分隔子串的任何顺序都是一致的:

代码语言:javascript
运行
复制
df2<-df%>%mutate(note=replace(note, 4, maybe[2]))

df2 %>% mutate(fwd_fender_mech_dmg = as.integer(str_split(note, ',') %>%
                      map(~str_detect(.x, "FE?ND.*(WEAR|DMG)")%>%
                      reduce(`|`))))

    SN fwd_fender                                       note fwd_fender_mech_dmg
1 1001          1                               FWD FNDR DMG                   1
2 1002          0                         MID BODY CHASS DMG                   0
3 1003          1   FWD FNDR EXCESS WEAR, MID BODY CHASS DMG                   1
4 1004          1 FWD FNDR PAINT SCRATCH, MID BODY CHASS DMG                   0

一些建议

你的数据似乎不“整洁”。“注意”变量偶尔会将两个数据值折叠为单个char元素。

如果将数据分开,那么在下游分析中,可能会使您的生活变得更容易,这样每个值都会有一个观察结果。

为此,您可能需要这样做:

代码语言:javascript
运行
复制
library(dpplyr)
library(stringr)
library(tidyr)

df %>% tidyr::separate_rows(note, sep='\\s*,\\s*') %>% #this separates the rows
        mutate(fwd_fender_mech_dmg = +str_detect(note, "FE?ND.*(WEAR|DMG)"))

# A tibble: 6 x 4
     SN fwd_fender note                   fwd_fender_mech_dmg
  <dbl>      <dbl> <chr>                                <int>
1  1001          1 FWD FNDR DMG                             1
2  1002          0 MID BODY CHASS DMG                       0
3  1003          1 FWD FNDR EXCESS WEAR                     1
4  1003          1 MID BODY CHASS DMG                       0
5  1004          1 MID BODY CHASS DMG                       0
6  1004          1 FWD FNDR PAINT SCRATCH                   0
票数 1
EN

Stack Overflow用户

发布于 2021-09-22 23:50:05

我建议使用tidyverse中的case_when函数:

代码语言:javascript
运行
复制
df %>% 
  mutate(fwd_fender_mech_dmg = case_when(grepl("FWD FNDR DMG", note) ~ 1,
                                         grepl("FWD FNDR EXCESS WEAR", note) ~ 1,
                                         TRUE ~ 0))

输出:

代码语言:javascript
运行
复制
    SN fwd_fender                                       note fwd_fender_mech_dmg
1 1001          1                               FWD FNDR DMG                   1
2 1002          0                         MID BODY CHASS DMG                   0
3 1003          1   FWD FNDR EXCESS WEAR, MID BODY CHASS DMG                   1
4 1004          1 MID BODY CHASS DMG, FWD FNDR PAINT SCRATCH                   0
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69292016

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档