【问题标题】:How to create a variable with a character chain present in two vectors如何创建具有两个向量中存在的字符链的变量
【发布时间】:2021-08-05 13:59:30
【问题描述】:

我有这个data.frame

data <- structure(list(pos = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10), c = c("AUSTOP", 
                                                                     "ATIP;AITUO", "BERTUI", "BHTREAK;PAERJR;KIEYTU", "FRTEU3", "IRTUFH", 
                                                                     "HAZEB", "ERTUJG;JIRTUE;HERTYE", "DAIER1", "ZERV")), 
                  class = "data.frame", row.names = c(NA, 
                                                      -10L))
  pos                     c
1    1                AUSTOP
2    2            ATIP;AITUO
3    3                BERTUI
4    4 BHTREAK;PAERJR;KIEYTU
5    5                FRTEU3
6    6                IRTUFH
7    7                 HAZEB
8    8  ERTUJG;JIRTUE;HERTYE
9    9                DAIER1
10  10                  ZERV

还有这两个向量:

xa <- c("AUSTOP", "HTURIE", "IRTUFH", "JEURTU", "AITUO", "ERTUJG", 
        "HERTYE", "DAIER", "ZERV1", "BERTUI")
xb <- c("ERTUJG", "TYUINJ", "HERTYE", "AUSTOP", "ERTBGT", "POKNFR")

我想为每一行创建另一个变量 new2,其中所有字符链都存在于 c 变量和 xa AND xb 向量中,如下所示:

   pos                     c          new1   new2
1    1                AUSTOP        AUSTOP AUSTOP
2    2            ATIP;AITUO         AITUO   <NA>
3    3                BERTUI        BERTUI   <NA>
4    4 BHTREAK;PAERJR;KIEYTU          <NA>   <NA>
5    5                FRTEU3          <NA>   <NA>
6    6                IRTUFH        IRTUFH   <NA>
7    7                 HAZEB          <NA>   <NA>
8    8  ERTUJG;JIRTUE;HERTYE ERTUJG;HERTYE ERTUJG
9    9                DAIER1          <NA>   <NA>
10  10                  ZERV          <NA>   <NA>

我问了一个类似的问题,只用一个向量(示例中的 xa)做同样的事情以获得 new1,但我不知道如何调整代码(见下文)以匹配两个向量。

library(dplyr)
library(stringr)
library(purrr)
data %>% 
    mutate(new = map_chr(str_extract_all(c, str_c("\\b(", str_c(xa,
        collapse="|"), ")\\b")), str_c, collapse=";"))

如果 tidyverse 有解决方案,那就太好了。 感谢您的帮助。

【问题讨论】:

  • 在您的示例中,您同时拥有AUSTOPAUTOSTOP。我认为其中一个应该更正。
  • 您能否更具体地说明您是如何从一个步骤到另一个步骤的?我无法说出您希望向量之间的关联程度以及 new1 之间的关联程度,尤其是因为 xb 更短。此外,您可能会遇到名为 c 的变量的问题(或者只是很难调试),因为这已经是您经常使用的函数

标签: r dataframe dplyr


【解决方案1】:

您可以将map2_chr 用于两个变量。

library(dplyr)
library(stringr)
library(purrr)

data %>% 
  mutate(new = map2_chr(str_extract_all(c, str_c("\\b(", str_c(xa,collapse="|"), ")\\b")), 
                        str_extract_all(c, str_c("\\b(", str_c(xb,collapse="|"), ")\\b")), 
                        ~str_c(intersect(.x, .y), collapse=";")))

【讨论】:

    【解决方案2】:

    你可以使用

    library(dplyr)
    library(stringr)
    library(purrr)
    
    data %>% 
      tibble() %>% 
      mutate(d = str_split(c, ";")) %>% 
      mutate(new_1 = map_chr(d, ~paste(intersect(.x, xa), collapse = ";")),
             new_2 = map_chr(d, ~paste(intersect(.x, xb), collapse = ";")),
             .keep = "unused") %>% 
      na_if("")
    

    得到

    # A tibble: 10 x 4
         pos c                     new_1         new_2        
       <dbl> <chr>                 <chr>         <chr>        
     1     1 AUSTOP                AUSTOP        AUSTOP           
     2     2 ATIP;AITUO            AITUO         NA           
     3     3 BERTUI                BERTUI        NA           
     4     4 BHTREAK;PAERJR;KIEYTU NA            NA           
     5     5 FRTEU3                NA            NA           
     6     6 IRTUFH                IRTUFH        NA           
     7     7 HAZEB                 NA            NA           
     8     8 ERTUJG;JIRTUE;HERTYE  ERTUJG;HERTYE ERTUJG;HERTYE
     9     9 DAIER1                NA            NA           
    10    10 ZERV                  NA            NA   
    

    首先,我们创建一个新列 d,其中包含拆分列 c。这是必要的,比较不同的词。

    接下来我们使用map_chr 来创建一个新的字符向量:map_chr 的第一个参数是d,我们想将每个元素(您的拆分词列表)与xa(或@987654329 @)。对于intersect(.x, xa),第一个参数是d 的当前元素:在第1 行,即"AUSTOP",对于第2 行,"ATIP""AITUO" 存储在一个列表中。这些元素与xa 进行比较并返回,如果它们也存在于xa 中。接下来我们将paste 生成的元素放在一起。这相当于stringr::str_c~ 表示purrr-version 一个没有名字的函数,类似于function(x) { do something },经常用在apply-familiy 函数中。由于我们不再需要列d,我们使用.keep = "unused" 将其删除。 select(-d) 作为下一个管道步骤也是一个可能的选择。 最后我们将不匹配时创建的空字符串""替换为NA

    【讨论】:

    • 太棒了,它似乎工作得很好。谢谢你。你能解释一下它是如何工作的吗?
    • 我不明白的第一件事: d 列的变异步骤。我已经使用了 str_split 函数,但通常它会拆分字符链(例如:str_split("a;b") 给出 "a"、"b" 在这里,中间结果中没有字符。
    • 第二件事:在第二个变异步骤中,你能解释一下 map_chr 函数是如何工作的吗?我也猜想 .x 指的是 c 列,但我也不明白 .x 是如何工作的。
    • str_split 实际上返回一个 list 的字符向量。所以d列包含10个lists,其中一些长度为1,两个长度为3,一个长度为2。我使用tibble作为数据结构,所以你可以看到,元素实际上是列表.
    • 非常感谢您的解释。这一点现在很清楚了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-24
    • 1970-01-01
    • 2022-11-01
    • 1970-01-01
    • 2020-09-16
    • 1970-01-01
    相关资源
    最近更新 更多