str_replace 在同一列中进行多次替换 - dplyr,stringr

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

我有这个数据框:

df <- structure(list(Stratigraphy = c("B", "B", "B", "B", "B", "B", 
"B", "B", "B", "B", "K", "F", "B", "B", "E", "B-C", "B-C", "B-C", 
"?", "B-C", "C?", "C?", "B-C", "B-C", "B-C", "?", "E-F-", "E-F-", 
"E-F-", "C", "F", "F", "E", "E", "B", "F", "F", "F", "F", "F", 
"F", "B", "D?", "E", "E", "E", "E", "E", "?", "F", "F", "F", 
"F", "F", "F", "F", "F", "F", "F", "F", "F", "F", "F", "E-F", 
"F", "G", "G", "G", "D", "C", "Finf", "Finf", "Finf", "D", "C", 
"C", "C", "C", "C", "C", "C", "C", "C", "C", "D", "C?", "G", 
"G", "G", "G", "G", "G", "G", "G", "G", "G", "D", "D", "Dmoy", 
"G", "G-G", "G-G", "G-G", "B-C", "G", "G-G", "G-G", "G-G", "D", 
"C", "F", "D", "D", "C", "C", "C", "C", "Dupper", "Dupper", "Dupper", 
"B", "B", "B", "F", "G", "G", "G", "G", "G", "G", "G", "G", "G", 
"C", "C", "C", "C", "C", "C", "E", "?", "F-F", "E-E", "C", "C", 
"C", "C", "C", "C", "C", "C", "C", "C?", "C?", "C?", "C?", "G", 
"G", "B", "?", "B", "B", "G", "G", "C", "?", "B-B", "B", "G-G", 
"G", "G", "G", "C(C?)", "F", "F", "F", "F", "F", "F", "F", "F", 
"F", "F", "F", "F", "F", "F", "F", "F", "F", "F", "L", "L", "K", 
"C", "C", "G", "G", "G", "J", "J", "K", "K", "F", NA, "L", "L", 
"L", "L", "L", NA, NA, "E", "E", "G", "G", "G", "G", "G", "?", 
"E", NA, NA, "E", "E", "E", "E", "E", "E", "E", "E", "E", "E", 
"E", "E", "?", "?", "C", "H-H", "G-G", "G-G", "G-G", "G-G", "G-G", 
"G-G", "G-G", "G-G", "G-G", "G-G", "G-G", "G-G", "G-G", "G-G", 
"F-F", "F-F", "F-F", "F-F", "F-F", "C", "C", "L", "G-G", "H", 
"F", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", NA, 
"B"), MD = c(8.33333333333333, 9.17666666666667, NaN, NaN, 9.17, 
NaN, 8.11, 11.6, 9.17666666666667, 9.03, 16.85, 4.785, 15.01, 
14.85, NaN, 9.34, 16.6633333333333, NaN, NaN, 14.49, NaN, NaN, 
NaN, NaN, NaN, NaN, NaN, NaN, NaN, 13.5833333333333, NaN, 13.25, 
15.1466666666667, NaN, NaN, 7.96333333333333, NaN, NaN, 16.7466666666667, 
NaN, 14.1333333333333, 13.6166666666667, NaN, NaN, 10.0066666666667, 
NaN, 13.0966666666667, NaN, NaN, NaN, NaN, NaN, 8.41, NaN, NaN, 
12.6466666666667, NaN, NaN, NaN, NaN, 13.5233333333333, 17.53, 
NaN, NaN, NaN, 9.53, NaN, 16.1666666666667, 9.39, 13.0133333333333, 
12.9433333333333, NaN, NaN, 13.7633333333333, 13.9466666666667, 
14.4566666666667, 13.21, 12.71, 12.86, 9.03666666666667, NaN, 
NaN, 9.67, NaN, 9.3, 11.3433333333333, 13.54, 14.94, NaN, 9.32333333333333, 
17.9, 9.99, NaN, NaN, NaN, 15.06, 13.11, NaN, 13.7633333333333, 
NaN, 15.1333333333333, 8.67, 13.1066666666667, 17.52, NaN, 19.2133333333333, 
12.49, 18.5033333333333, 12.09, NaN, 11.1533333333333, NaN, NaN, 
NaN, 8.44666666666667, 8.00333333333333, 9.68666666666667, NaN, 
14.2566666666667, NaN, 14.26, 11.0533333333333, 8.70666666666667, 
10.5666666666667, 17.81, 16.5633333333333, NaN, NaN, NaN, NaN, 
NaN, NaN, NaN, 15.2866666666667, NaN, NaN, 14.1466666666667, 
NaN, 14.27, 14.5533333333333, NaN, 13.0933333333333, 10.19, NaN, 
NaN, NaN, NaN, NaN, 12.7133333333333, NaN, 5.84, 14.9133333333333, 
NaN, NaN, NaN, NaN, NaN, 12.91, 9.37333333333333, NaN, 9.24, 
12.54, 9.98, 11.9066666666667, 14.4833333333333, NaN, 18.8, NaN, 
10.6966666666667, 10.5266666666667, 10.4366666666667, 15.53, 
13.26, NaN, NaN, 14.09, NaN, NaN, 9.16666666666667, NaN, NaN, 
NaN, NaN, 8.29666666666667, NaN, 9.73, NaN, 9.97, NaN, 17.53, 
NaN, NaN, 13.175, NaN, NaN, 13.4533333333333, NaN, NaN, NaN, 
16.02, NaN, 14.82, 9.17333333333333, NaN, NaN, NaN, NaN, 12.3233333333333, 
12.3266666666667, 12.47, NaN, NaN, NaN, NaN, NaN, 16.8666666666667, 
NaN, NaN, 16.9566666666667, NaN, 14.9133333333333, NaN, NaN, 
10.42, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, 
NaN, NaN, 8.36666666666667, 9.9, 10.22, 14.1366666666667, 13.93, 
NaN, NaN, 10.67, 17.12, 14.89, 11.5133333333333, 11.6266666666667, 
15.6466666666667, 17.7466666666667, 11.09, 15.21, 17.8533333333333, 
NaN, NaN, 19.7333333333333, NaN, 13.8733333333333, 16.8033333333333, 
15.27, 13.11, NaN, 13.5766666666667, 10.7166666666667, 13.33, 
13.33, NaN, NaN, 12.5833333333333, 12.5833333333333, NaN, NaN, 
14.2266666666667, 10.83, 8.97, 10.0166666666667), BL = c(12.4866666666667, 
13.3666666666667, NaN, 13.1, 12.43, NaN, 12.18, 13.5, NaN, 12.5566666666667, 
15.89, 6.18, 12.86, 12.7933333333333, NaN, 7.845, 14.02, NaN, 
NaN, 13.1566666666667, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, 
NaN, 16.4133333333333, NaN, 16.0733333333333, 13.1266666666667, 
NaN, NaN, 9.41666666666667, NaN, NaN, 12.6, NaN, 14.3233333333333, 
11.54, NaN, NaN, NaN, 16.56, 15.5066666666667, NaN, NaN, NaN, 
NaN, NaN, 11.1766666666667, NaN, NaN, 16.13, NaN, NaN, NaN, NaN, 
16.2466666666667, NaN, NaN, NaN, NaN, 12.61, NaN, 14.7633333333333, 
11.7833333333333, 12.1133333333333, NaN, NaN, NaN, 14.5633333333333, 
12.68, 13.13, 15, 13.9633333333333, 13.74, NaN, NaN, NaN, 10.81, 
NaN, 6.11, 9.3, 15.165, NaN, NaN, NaN, 15.7333333333333, 11.6766666666667, 
NaN, NaN, NaN, 14.16, 12.48, NaN, 14.5633333333333, NaN, 13.73, 
9.92666666666667, 14.0066666666667, 16.3066666666667, NaN, 19.2933333333333, 
19.1, 17.0866666666667, 11.7233333333333, NaN, NaN, NaN, NaN, 
12.43, 10.1466666666667, 9.91666666666667, 12.44, NaN, 16.28, 
NaN, 13.37, 13.08, 12.8466666666667, 11.9633333333333, 15.4066666666667, 
14.54, NaN, NaN, NaN, NaN, NaN, NaN, NaN, 13.26, NaN, NaN, NaN, 
NaN, NaN, 15.4933333333333, NaN, 11.2966666666667, 12.1866666666667, 
NaN, NaN, NaN, NaN, 14, 10.1033333333333, NaN, 5.96, 16.45, NaN, 
NaN, NaN, NaN, 10.155, 11.1833333333333, 10.72, NaN, 13.4966666666667, 
10.7633333333333, 7.505, 10.04, 12.96, NaN, 14.8233333333333, 
NaN, 11.9866666666667, NaN, 17.2833333333333, 16.6566666666667, 
11.41, NaN, NaN, 15.3, NaN, NaN, 12.86, NaN, NaN, NaN, NaN, 11.7466666666667, 
NaN, 11.67, NaN, NaN, NaN, NaN, NaN, NaN, 11.6533333333333, NaN, 
NaN, 12.38, NaN, NaN, NaN, 16.2, NaN, 16.69, 13.2166666666667, 
NaN, NaN, NaN, NaN, 12.67, 13.4666666666667, 11.8166666666667, 
NaN, NaN, NaN, NaN, NaN, 15.7333333333333, NaN, NaN, 14.84, NaN, 
13.37, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, 
NaN, NaN, NaN, NaN, NaN, 11.9866666666667, NaN, NaN, 12.6466666666667, 
12.0533333333333, NaN, NaN, 12.0833333333333, 14.9166666666667, 
13.9666666666667, 11.5333333333333, 12.81, 13.82, 14.9133333333333, 
13.9733333333333, NaN, NaN, NaN, NaN, NaN, NaN, 14.4633333333333, 
NaN, 12.4733333333333, 13.2333333333333, NaN, 14.1033333333333, 
10.4966666666667, 12.22, 12.22, NaN, NaN, 14.66, 14.66, NaN, 
NaN, 12.67, 12.07, 10.25, 13.555)), row.names = c(NA, -277L), class = c("tbl_df", 
"tbl", "data.frame"))

如果您看到列的值

Stratigraphy
...

sort(unique(df$Stratigraphy))

 [1] "?"      "B"      "B-B"    "B-C"    "C"      "C(C?)"  "C?"     "D"      "D?"     "Dmoy"   "Dupper"
[12] "E"      "E-E"    "E-F"    "E-F-"   "F"      "F-F"    "Finf"   "G"      "G-G"    "H"      "H-H"   
[23] "J"      "K"      "L"   

...你可以意识到有几个 Strata 可能是重复的。例如,我想将

B-B
中的所有
B
C(C?)
中的所有
C
,等等

出于这个原因,我使用

str_replace
来适应每种情况:

df2 <- df %>%
  mutate(Stratigraphy = str_replace(Stratigraphy, "B-B" ,"B")) %>% 
  mutate(Stratigraphy = str_replace(Stratigraphy, "C(C?)", "C")) %>%
  mutate(Stratigraphy = str_replace(Stratigraphy, "C?", "C")) %>%
  mutate(Stratigraphy = str_replace(Stratigraphy, "D?", "D")) %>%
  mutate(Stratigraphy = str_replace(Stratigraphy, "Dmoy", "D")) %>%
  mutate(Stratigraphy = str_replace(Stratigraphy, "Dupper", "D")) %>%
  mutate(Stratigraphy = str_replace(Stratigraphy, "E-E", "E")) %>%
  mutate(Stratigraphy = str_replace(Stratigraphy, "F-F", "F")) %>%
  mutate(Stratigraphy = str_replace(Stratigraphy, "Finf", "F")) %>%
  mutate(Stratigraphy = str_replace(Stratigraphy, "G-G", "G")) %>%
  mutate(Stratigraphy = str_replace(Stratigraphy, "H-H", "H"))

然而,结果并不是我想要的:

df2$Stratigraphy
  [1] "DCB"    "DCB"    "DCB"    "DCB"    "DCB"    "DCB"    "DCB"    "DCB"    "DCB"    "DCB"    "DCK"   
 [12] "DCF"    "DCB"    "DCB"    "DCE"    "DCB-C"  "DCB-C"  "DCB-C"  "DC?"    "DCB-C"  "DC?"    "DC?"   
 [23] "DCB-C"  "DCB-C"  "DCB-C"  "DC?"    "DCE-F-" "DCE-F-" "DCE-F-" "DC"     "DCF"    "DCF"    "DCE"   
 [34] "DCE"    "DCB"    "DCF"    "DCF"    "DCF"    "DCF"    "DCF"    "DCF"    "DCB"    "DCD?"   "DCE"   
 [45] "DCE"    "DCE"    "DCE"    "DCE"    "DC?"    "DCF"    "DCF"    "DCF"    "DCF"    "DCF"    "DCF"   
 [56] "DCF"    "DCF"    "DCF"    "DCF"    "DCF"    "DCF"    "DCF"    "DCF"    "DCE-F"  "DCF"    "DCG"   
 [67] "DCG"    "DCG"    "DCD"    "DC"     "DCF"    "DCF"    "DCF"    "DCD"    "DC"     "DC"     "DC"    
 [78] "DC"     "DC"     "DC"     "DC"     "DC"     "DC"     "DC"     "DCD"    "DC?"    "DCG"    "DCG"   
 [89] "DCG"    "DCG"    "DCG"    "DCG"    "DCG"    "DCG"    "DCG"    "DCG"    "DCD"    "DCD"    "DCD"   
[100] "DCG"    "DCG"    "DCG"    "DCG"    "DCB-C"  "DCG"    "DCG"    "DCG"    "DCG"    "DCD"    "DC"    
[111] "DCF"    "DCD"    "DCD"    "DC"     "DC"     "DC"     "DC"     "DCD"    "DCD"    "DCD"    "DCB"   
[122] "DCB"    "DCB"    "DCF"    "DCG"    "DCG"    "DCG"    "DCG"    "DCG"    "DCG"    "DCG"    "DCG"   
[133] "DCG"    "DC"     "DC"     "DC"     "DC"     "DC"     "DC"     "DCE"    "DC?"    "DCF"    "DCE"   
[144] "DC"     "DC"     "DC"     "DC"     "DC"     "DC"     "DC"     "DC"     "DC"     "DC?"    "DC?"   
[155] "DC?"    "DC?"    "DCG"    "DCG"    "DCB"    "DC?"    "DCB"    "DCB"    "DCG"    "DCG"    "DC"    
[166] "DC?"    "DCB"    "DCB"    "DCG"    "DCG"    "DCG"    "DCG"    "DC(C?)" "DCF"    "DCF"    "DCF"   
[177] "DCF"    "DCF"    "DCF"    "DCF"    "DCF"    "DCF"    "DCF"    "DCF"    "DCF"    "DCF"    "DCF"   
[188] "DCF"    "DCF"    "DCF"    "DCF"    "DCL"    "DCL"    "DCK"    "DC"     "DC"     "DCG"    "DCG"   
[199] "DCG"    "DCJ"    "DCJ"    "DCK"    "DCK"    "DCF"    NA       "DCL"    "DCL"    "DCL"    "DCL"   
[210] "DCL"    NA       NA       "DCE"    "DCE"    "DCG"    "DCG"    "DCG"    "DCG"    "DCG"    "DC?"   
[221] "DCE"    NA       NA       "DCE"    "DCE"    "DCE"    "DCE"    "DCE"    "DCE"    "DCE"    "DCE"   
[232] "DCE"    "DCE"    "DCE"    "DCE"    "DC?"    "DC?"    "DC"     "DCH"    "DCG"    "DCG"    "DCG"   
[243] "DCG"    "DCG"    "DCG"    "DCG"    "DCG"    "DCG"    "DCG"    "DCG"    "DCG"    "DCG"    "DCG"   
[254] "DCF"    "DCF"    "DCF"    "DCF"    "DCF"    "DC"     "DC"     "DCL"    "DCG"    "DCH"    "DCF"   
[265] "DCB"    "DCB"    "DCB"    "DCB"    "DCB"    "DCB"    "DCB"    "DCB"    "DCB"    "DCB"    "DCB"   
[276] NA       "DCB"

我该如何进行?我做错了什么?

r dplyr replace stringr
3个回答
1
投票

我们可以提取大写、检查和重构:

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

df2 <-
  df |>
  mutate(elements = str_extract_all(Stratigraphy, "[A-Z]")) |>
  unnest_wider(elements, names_sep = "_") |>
  mutate(newStratigraphy = if_else(elements_1 == elements_2 | is.na(elements_2),
                                   elements_1,
                                   paste0(elements_1, "-", elements_2))) 

注意。出于交际原因,我取消了列的嵌套。如果你想要更紧凑的代码,你可以直接在嵌套列表上工作

elements

检查输出:

df2 |>
  count(Stratigraphy, newStratigraphy) |>
  print(n = 26)

输出:

# A tibble: 26 × 3
   Stratigraphy newStratigraphy     n
   <chr>        <chr>           <int>
 1 ?            NA                  9
 2 B            B                  33
 3 B-B          B                   1
 4 B-C          B-C                 8
 5 C            C                  38
 6 C(C?)        C                   1
 7 C?           C                   7
 8 D            D                   8
 9 D?           D                   1
10 Dmoy         D                   1
11 Dupper       D                   3
12 E            E                  24
13 E-E          E                   1
14 E-F          E-F                 1
15 E-F-         E-F                 3
16 F            F                  46
17 F-F          F                   6
18 Finf         F                   3
19 G            G                  39
20 G-G          G                  22
21 H            H                   1
22 H-H          H                   1
23 J            J                   2
24 K            K                   4
25 L            L                   8
26 NA           NA                  6

或者,在您尝试使用

str_replace
之后:当您想重新编码类别而不是在字符串中进行替换时,您的朋友是
recode
,从
dplyr >= 1.1.0
case_match
取代:

library(dplyr)

df |>
  mutate(newStratigraphy = recode(Stratigraphy,
                                  "B-B" = "B",
                                  "C(C?)" = "C",
                                  "C?" = "C",
                                  "D?" = "D",
                                  "Dmoy" = "D",
                                  "Dupper" = "D",
                                  "E-E" = "E",
                                  "F-F" = "F",
                                  "Finf" = "F",
                                  "G-G" = "G",
                                  "H-H" = "H")) 
df |>
  mutate(newStratigraphy = case_match(Stratigraphy,
                                     "B-B" ~ "B",
                                     c("C(C?)", "C?") ~ "C",
                                     c("D?", "Dmoy", "Dupper") ~ "D",
                                     "E-E" ~ "E",
                                     c("F-F", "Finf") ~ "F",
                                     "G-G" ~ "G",
                                     "H-H" ~ "H",
                                     .default = Stratigraphy))

然而,有 26 个类别,它可能有点长..


0
投票

你可以简单地

str_extract
第一个字符(
str_extract
默认只提取第一个匹配,所以位置不需要指定)

library(dplyr)
library(stringr)
df %>%
  mutate(Stratigraphy = str_extract(Stratigraphy, "."))

0
投票
df |> 
  mutate(Stratigraphy = ifelse(
           Stratigraphy != "B-C", substr(Stratigraphy, 1,1), 
              Stratigraphy)) 

或者更好的做法是制作一个不想更改的字符串向量,定义

%in%
的反义词,然后执行以下操作:

not_to_change <-  c("B-C")
`%nin%`  <- Negate(`%in%`)
ddf <- df |> 
  mutate(Stratigraphy = ifelse(Stratigraphy %nin% not_to_change, substr(Stratigraphy, 1,1), Stratigraphy))

unique(ddf$Stratigraphy)
 #[1] "B"   "K"   "F"   "E"   "B-C" "?"   "C"   "D"   "G"   "L"   #"J"  
#[12] NA    "H" 
© www.soinside.com 2019 - 2024. All rights reserved.