用R stringr中的vector替换列值

时间:2018-07-02 08:53:18

标签: r dplyr stringr

我正在尝试用stringr中的向量来变异和替换列值。我遇到了一些我认为与函数回收方式有关的问题。我是R的新手,似乎无法弄清楚我在做什么错。

我要更改的列:

[1] "3+4" "3+3"  NA    "3+4"  NA   "4+3" "4+4" "4+3" "4+4" "5+4" "4+3" "4+3" "3+4" "4+3"
[15] "4"   NA    "4+3" NA    NA    "3+4" "4+5" NA    "3+4" NA    NA    "3+4" NA    "3+4"
[29] "3+4" "3+4" "3+3" "3"   NA    "3+3" "3+3" NA    "4+5" NA    "3+3" "3+4" "4+4" "3+4"
[43] "4+4" "3+3" "3+4" "3+4" NA    "4+3" "4+3" "3+3" "3+3" "3+4"

我想将其更改为3+3 = 13+4 = 24+3 = 34+4 = 44+5 = 55+5 = 5。这是前列腺癌的格里森评分和格里森等级组。

有时运行一个就可以了:

mrgb_trus <- mrgb_trus %>% 
mutate(MRGGG = str_replace_all(MRGB_gleason, "3\\+4", "2"))

添加向量:

mrgb_trus <- mrgb_trus %>% 
mutate(MRGGG = str_replace_all(MRGB_gleason, c("3\\+3", "3\\+4", "4\\+3", 
                                      "4\\+4", "4\\+5", "5\\+4", 
                                      "5\\+5"), c("1", "2", "3", 
                                      "4", "5", "5", "5")))                                                  

产生警告

Warning message:
In stri_replace_first_regex(string, pattern,   fix_replacement(replacement),  :
longer object length is not a multiple of shorter object length

,并且不返回所需的输出。我究竟做错了什么?如您所见,还有一些NA和两个值"3""4"与模式不匹配。我还想将NA更改为03,将4更改为1

2 个答案:

答案 0 :(得分:0)

其中一种方法可能是

#define your mapping here
lhs <- c('3+3', '3+4', '4+3', '4+4', '4+5', '5+5', '3', '4')
rhs <- c(1, 2, 3, 4, 5, 5, 1, 1)

df$col1_new <- ifelse(is.na(df$col1), 0, rhs[match(df$col1, lhs)])

给出

> df$col1_new
 [1]  2  1  0  2  0  3  4  3  4 NA  3  3  2  3  1  0  3  0  0  2  5  0  2  0  0  2  0  2  2  2  1  1  0  1  1  0  5
[38]  0  1  2  4  2  4  1  2  2  0  3  3  1  1  2

请注意,示例数据中仍缺少5+4的定义。


示例数据

df <- structure(list(col1 = c("3+4", "3+3", NA, "3+4", NA, "4+3", "4+4", 
"4+3", "4+4", "5+4", "4+3", "4+3", "3+4", "4+3", "4", NA, "4+3", 
NA, NA, "3+4", "4+5", NA, "3+4", NA, NA, "3+4", NA, "3+4", "3+4", 
"3+4", "3+3", "3", NA, "3+3", "3+3", NA, "4+5", NA, "3+3", "3+4", 
"4+4", "3+4", "4+4", "3+3", "3+4", "3+4", NA, "4+3", "4+3", "3+3", 
"3+3", "3+4")), .Names = "col1", row.names = c(NA, -52L), class = "data.frame")

答案 1 :(得分:0)

要解决您遇到的错误:str_replace_all中的“全部”不是要用一个向量中的所有值替换另一个向量中的所有值。相反,它更像是在reprex中设置全局标志。用于这种情况:

stringr::str_replace("a2bb4", "\\d", "x")
#> [1] "axbb4"
stringr::str_replace_all("a2bb4", "\\d", "x")
#> [1] "axbbx"

您想要的是将一组值重新编码为另一组值。这是3种基于tidyverse的方式。

#  3+3 = 1, 3+4 = 2, 4+3 = 3, 4+4 = 4, 4+5 = 5, 5+5 = 5

library(tidyverse)

x <- c("3+4", "3+3",  NA, "3+4",  NA, "4+3", "4+4", "4+3", "4+4", "5+4", "4+3", "4+3", "3+4", "4+3", "4",   NA, "4+3", NA, NA, "3+4", "4+5", NA, "3+4", NA, NA, "3+4", NA, "3+4", "3+4", "3+4", "3+3", "3",   NA, "3+3", "3+3", NA, "4+5", NA, "3+3", "3+4", "4+4", "3+4", "4+4", "3+3", "3+4", "3+4", NA, "4+3", "4+3", "3+3", "3+3", "3+4")

首先,dplyr::recode采用命名矢量,其中名称是旧值,而元素是新值。

recode(x, "3+3" = "1", "3+4" = "2", "4+3" = "3", "4+4" = "4", "4+5" = "5", "5+5" = "5")
#>  [1] "2"   "1"   NA    "2"   NA    "3"   "4"   "3"   "4"   "5+4" "3"  
#> [12] "3"   "2"   "3"   "4"   NA    "3"   NA    NA    "2"   "5"   NA   
#> [23] "2"   NA    NA    "2"   NA    "2"   "2"   "2"   "1"   "3"   NA   
#> [34] "1"   "1"   NA    "5"   NA    "1"   "2"   "4"   "2"   "4"   "1"  
#> [45] "2"   "2"   NA    "3"   "3"   "1"   "1"   "2"

我偏爱这样的任务已成为决定因素,因为我将这些离散的文本值视为级别。 forcats使重新编码和操纵因子水平变得容易。在这种情况下,我仅使用fct_recode(它以与recode相反的顺序获取新旧值!),但是如果您有多个级别已更改为"5",则例如,您可以使用fct_collapse。您还可以通过使用以下因素得到警告:尝试重新编码不存在的级别,并且获得了当前因素的列表,这使您看到尚未重新编码"5+4"

fct_recode(as.factor(x), "1" = "3+3", "2" = "3+4", "3" = "4+3", "4" = "4+4", "5" = "4+5", "5" = "5+5")
#> Warning: Unknown levels in `f`: 5+5
#>  [1] 2    1    <NA> 2    <NA> 3    4    3    4    5+4  3    3    2    3   
#> [15] 4    <NA> 3    <NA> <NA> 2    5    <NA> 2    <NA> <NA> 2    <NA> 2   
#> [29] 2    2    1    3    <NA> 1    1    <NA> 5    <NA> 1    2    4    2   
#> [43] 4    1    2    2    <NA> 3    3    1    1    2   
#> Levels: 3 1 2 4 5 5+4

第三种方法可能是最可持续的,特别是如果您需要在一个月内回到此方法或将信息传递给同事:制作查询表并加入。

lookup <- tribble(
  ~old_val, ~new_val,
  "3+3",     "1",
  "3+4",     "2",
  "4+3",     "3",
  "4+4",     "4",
  "4+5",     "5",
  "5+5",     "5"
)
tibble(x = x) %>%
  left_join(lookup, by = c("x" = "old_val"))
#> # A tibble: 52 x 2
#>    x     new_val
#>    <chr> <chr>  
#>  1 3+4   2      
#>  2 3+3   1      
#>  3 <NA>  <NA>   
#>  4 3+4   2      
#>  5 <NA>  <NA>   
#>  6 4+3   3      
#>  7 4+4   4      
#>  8 4+3   3      
#>  9 4+4   4      
#> 10 5+4   <NA>   
#> # ... with 42 more rows

reprex package(v0.2.0)于2018-07-02创建。