改变与定义的字符串匹配的新列

mutate new column that matches to defined strings

我想 mutate 数据框的列之一取决于匹配的特定条件。我环顾四周,但到目前为止找不到一些巧妙的解决方案。

这是我使用的简单数据框

gr = rep(seq(1,2),each=3)
clas=c("A_1","A_2","A_3","A_4","A_5","A_6")

df <- data.frame(gr,clas)

> df
  gr clas
1  1  A_1
2  1  A_2
3  1  A_3
4  2  A_4
5  2  A_5
6  2  A_6

我想有机会 A_4、A_5 和 A_6 与 B_1、B_2 和 B_3

所以我尝试了

match <- paste('_',seq(4,6),sep='')
 df%>%
  mutate(clas=ifelse(clas %in% match,paste('B',seq(1,3),sep='_'),clas))

       gr clas
    1  1    1
    2  1    2
    3  1    3
    4  2    4
    5  2    5
    6  2    6

第二次尝试 grepl

df%>%
mutate(clas=ifelse(clas==grepl(paste(match,collapse='|'),clas),paste('B',seq(1,3),sep='_'),clas))

   gr clas
1  1    1
2  1    2
3  1    3
4  2    4
5  2    5
6  2    6

哪个是A的也没有了:)预期结果是;

   gr clas
1  1  A_1
2  1  A_2
3  1  A_3
4  2  B_1
5  2  B_2
6  2  B_3

谢谢!

编辑:我意识到如果数据 clas 列中有字母,这样做会更容易。但是,如果我们有这样的数据但没有 gr 列,我们该怎么做??

    clas
1   CD_1
2  X.2_2
3  K_3
4 12k3_4
5   .A_5
6   xy_6

预期输出是

    clas
1   CD_1
2  X.2_2
3  K_3
4 12kB_4
5   .B_5
6   xB_6

我想我正在寻找这样的解决方案

这是一个依赖于 df$gr 的基础 R 解决方案:

paste(LETTERS[df$gr], ave(df$gr, df$gr, FUN=seq_along), sep="_")
[1] "A_1" "A_2" "A_3" "B_1" "B_2" "B_3

LETTERS是拉丁文大写字母,LETTERS[1]是"A"。因此 "A" 和 "B" 被粘贴到由 seq_along 构造的 运行 计数的结果中,该计数使用 ave 按组重置。这两个以“_”为分隔符粘贴在一起。

这是dplyr解决方案:

df%>%group_by(gr)%>%dplyr::mutate(clas=paste0(toupper(letters[gr]),"_",row_number()))
#you can change toupper(letters[gr]) to LETTERS[gr]

# A tibble: 6 x 2
# Groups:   gr [2]
     gr  clas
  <int> <chr>
1     1   A_1
2     1   A_2
3     1   A_3
4     2   B_1
5     2   B_2
6     2   B_3

我会尝试使用 base R: 来专门解决这个问题:

首先确保你的矢量是字符形式。我把上面的table叫做B

  B[,1]=as.character(B[,1])
  B[4:6,1]=sapply(B$clas[4:6],function(i) {substr(i,nchar(i)-2,nchar(i)-2)<-"B";i})
  B
     clas
 1   CD_1
 2  X.2_2
 3  K_3
 4 12kB_4
 5   .B_5
 6   xB_6