【问题标题】:paste only part of a vector according to a T/F colum根据 DF 列仅粘贴向量的一部分
【发布时间】:2021-11-12 04:22:17
【问题描述】:

假设我有一个数据框,其中包含显示颜色的物种。

df<-data.frame(name=paste("spec",1:5),
         ind=c("blue;green","red","green","red;green;blue",""))

一些(蓝色和红色)颜色实际上意味着什么。我可以 grepl() 他们并获得一个 T/F 列

df$isredorblue&lt;-grepl("blue|red",df$ind)

但现在我想知道哪些有意义的颜色显示在一列中。

想要的结果是:

> df
    name            ind isredorblue searchcolor
1 spec 1     blue;green        TRUE        blue
2 spec 2            red        TRUE         red
3 spec 3          green       FALSE       other
4 spec 4 red;green;blue        TRUE    red;blue
5 spec 5                      FALSE       other

我已经尝试使用 [^]+ 的 gsub 但这并没有真正起作用,因为它匹配 所有 字母,因此“r”或“e”或“d”不是“red”。 ..

>     gsub("[^red]+","",df$ind)
[1] "eree"    "red"     "ree"     "redreee" ""    

现在我正在考虑使用 strsplit ......但似乎无法弄清楚我的下一步

blabla<-strsplit(df$ind, split=";") 


blabla<-blabla[-which(!blabla %in% c("red","blue"))]

> blabla
[[1]]
[1] "red"

请记住这是一个 reprex,我的实际数据框要大得多,并且有不同的指标“颜色”对不同的事物很重要,所以我需要能够生成这些列尽可能少的步骤

【问题讨论】:

    标签: r string gsub


    【解决方案1】:

    这里有两种方法。

    1. 使用正则表达式 -

    这会从color 创建一个正则表达式模式,以从数据中的ind 列中提取。如果没有提取值,我们将空白替换为'other'

    color <- c('red', 'blue')
    pat <- paste0(color, collapse = '|')
    df$is_color_present <- grepl(pat, df$ind)
    df$searchcolor <- sapply(stringr::str_extract_all(df$ind, pat), paste0, collapse = ';')
    df$searchcolor[df$searchcolor == ''] <- 'other'
    df
    #    name            ind is_color_present searchcolor
    #1 spec 1     blue;green             TRUE        blue
    #2 spec 2            red             TRUE         red
    #3 spec 3          green            FALSE       other
    #4 spec 4 red;green;blue             TRUE    red;blue
    #5 spec 5                           FALSE       other
    
    1. 不使用正则表达式使用tidyverse -

    我们在; 上以长格式拆分数据,并仅保留color 中存在的那些值。

    library(dplyr)
    library(tidyr)
    
    df %>%
      separate_rows(ind, sep = ';') %>%
      group_by(name) %>%
      summarise(is_color_present = any(ind %in% color), 
                searchcolor = paste0(ind[ind %in% color], collapse = ';'), 
                searchcolor = replace(searchcolor, searchcolor == '', 'other'))
    

    【讨论】:

    • 我使用的是正则表达式版本...仅供参考,它会引发警告...“错误:'st_exctract_all' 不是从 'namespace:stringr' 导出的对象”
    • 是的,我认为str_extract_all 中缺少r
    • 是的 ;-),这就行了
    【解决方案2】:

    这是一个简洁的解决方案:

    library(dplyr)
    library(stringr)
    

    首先将所有目标颜色定义为一个向量:

    targets <- c('red', 'blue')
    

    现在使用转换为正则表达式交替模式的向量在新列中提取所需的颜色:

    df %>%
       mutate(colors = str_extract_all(ind, paste0(targets, collapse = "|")))
        name            ind    colors
    1 spec 1     blue;green      blue
    2 spec 2            red       red
    3 spec 3          green          
    4 spec 4 red;green;blue red, blue
    5 spec 5 
    

    如果您有许多颜色名称,其中一些可能共享相同的字母(例如“red”和“darkred”),您可能需要在颜色名称周围加上单词边界:

    df %>%
      mutate(colors = str_extract_all(ind, paste0("\\b(",paste0(targets, collapse = "|"), ")\\b")))
    

    这是另一个dplyr 解决方案(虽然不是最简洁的):

    df %>%
      mutate(
        blue = ifelse(grepl("blue", ind), "blue","other"),
        red = ifelse(grepl("red", ind), "red","other"),
        target = ifelse(blue=="blue"|red=="red", paste(red, blue), "other"),
        target = sub("^other\\s(?=blue|red)|(?<=blue|red)\\sother$", "", target, perl = TRUE)) %>%
      select(-c(3:5))
        name            ind   target
    1 spec 1     blue;green     blue
    2 spec 2            red      red
    3 spec 3          green    other
    4 spec 4 red;green;blue red blue
    5 spec 5                   other
    

    数据:

    df<-data.frame(name=paste("spec",1:5),
                   ind=c("blue;green","red","green","red;green;blue",""))
    

    【讨论】:

      猜你喜欢
      • 2016-01-31
      • 1970-01-01
      • 2017-07-29
      • 1970-01-01
      • 2015-11-27
      • 2020-06-11
      • 2016-07-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多