如何替换数据框中的特殊字符串? R

问题描述 投票:0回答:2

我有以下称为

result
的数据框。

手册.ID 自动识别 loc
NA PYPPYP L2
PIPpip NA L1
野蛮人 NA L5
NA 皮皮 L3
NA 皮皮,BerBar L3

我尝试用正确的标签替换同一标签的所有不同形式。例如,将所有 PIPPIP 和 PIPpip 替换为 Pippip 或将 Berbar 替换为 Barbar。为此,我根据名为

mutate
的所需文件使用带有
left_join
tesaurus
函数,该文件包含包含相同标签(tag_id)所有可能情况的列和包含正确标签(tag_ok)的列看起来像这样:

tag_id tag_ok
PYPPYP 皮皮
PIPpip 皮皮
皮皮 皮皮
野蛮人 野蛮人
BerBar 野蛮人

我使用以下代码。

library("plyr")
library("dplyr")
library("reshape")
library("data.table")
library("stringr")
library("tidyr")
library("openxlsx")

tesaurus <- read.xlsx("Requested_files/sp_tesaurus.xlsx", sheet = "tesaurus") %>%
  select(-bat_sp)

result <- result %>%
  left_join(tesaurus, by = c(MANUAL.ID = "tag_id")) %>%
  mutate(MANUAL.ID = coalesce(tag_ok, MANUAL.ID)) %>%
  select(-tag_ok) %>%
  left_join(tesaurus, by = c(AUTO.ID = "tag_id")) %>%
  mutate(AUTO.ID = coalesce(tag_ok, AUTO.ID)) %>%
  select(-tag_ok)

此代码适用于 MANUAL.ID 列,但适用于 AUTO.ID 列,因为特殊情况:Pippip,BerBar(一种情况下有两个标签)

我该如何解决?

r dplyr left-join mutate
2个回答
1
投票

我们可以将

str_replace_all
与命名向量一起使用

library(dplyr)
library(stringr)
library(tibble)
df %>% 
  mutate(across(ends_with("ID"), ~ str_replace_all(.x, deframe(tesaurus))))

-输出

   MANUAL.ID       AUTO.ID loc
1      <NA>        Pippip  L2
2    Pippip          <NA>  L1
3    Barbar          <NA>  L5
4      <NA>        Pippip  L3
5      <NA> Pippip,Barbar  L3

1
投票

我们可以这样做: Note我认为在tesaurus

Barbar
中的tag_id应该是
Berbar

注意 看看@akrun 的解决方案,它更优雅但一开始很难掌握。但是想法很巧妙,我们必须将双列数据框视为命名向量,第一列为名称,第二列为值,我们可以用 akrun 提供的更优雅的方式来实现它:

tesaurus <- structure(list(tag_id = c("PYPPYP", "PIPpip", "Pippip", "Berbar"
), tag_ok = c("Pippip", "Pippip", "Pippip", "Barbar")), class = "data.frame", row.names = c(NA, 
-4L))

数据:

df <- structure(list(MANUAL.ID = c(NA, "PIPpip", "Barbar", NA, NA), 
    AUTO.ID = c("PYPPYP", NA, NA, "Pippip", "Pippip,BerBar"), 
    loc = c("L2", "L1", "L5", "L3", "L3")), class = "data.frame", row.names = c(NA, 
-5L))

解决方案:

library(dplyr)
library(stringr)
library(tidyr)

df %>% 
  mutate(id = row_number()) %>% 
  separate_rows(everything()) %>% 
  mutate(across(-c(id, loc), ~ifelse(str_detect(., paste(tesaurus$tag_id, collapse = "|")),
                              tesaurus$tag_ok, .)
  )) %>% 
  summarise(across(everything(), ~toString(., na.rm=TRUE)), .by = c(id, loc)) %>% 
  mutate(across(-c(id, loc), ~ifelse(str_detect(., "NA"), NA_character_, .))) %>% 
  select(contains("ID"), loc, -id)
  
 MANUAL.ID AUTO.ID        loc  
  <chr>     <chr>          <chr>
1 NA        Pippip         L2   
2 Pippip    NA             L1   
3 Barbar    NA             L5   
4 NA        Barbar         L3   
5 NA        Pippip, BerBar L3  
© www.soinside.com 2019 - 2024. All rights reserved.