str_replace 在 mutate(across()) 中匹配来自 cur_column 的第 n 个字符

str_replace within mutate(across()) matching nth character from cur_column

我的目标总结

我有以下数据帧结构:

my.df <-data.frame("col1_A.C"=c("AA","AC","CC"),
                   "col2_A.T"=c("TT","AT","TT"),
                   "col3_C.G"=c("GG","CG","CG"))

my.df
#   col1_A.C col2_A.T col1_C.G
# 1       AA       TT       GG
# 2       AC       AT       CG
# 3       CC       TT       CG

对于每一列,我想用字符“R”替换与列名的倒数第三个字符匹配的任何字符。

使用上面的数据框,我想得到这个:

my.df2 <- data.frame("col1_A.C"=c("RR","RC","CC"),
                   "col2_A.T"=c("TT","RT","TT"),
                   "col3_C.G"=c("GG","RG","RG"))

my.df2
#   col1_A.C col2_A.T col1_C.G
# 1       RR       TT       GG
# 2       RC       RT       RG
# 3       CC       TT       RG

例如,在第一列中,列名是 col1_A.CA 是倒数第三个字符。因此,所有 A 都被替换为 R

到目前为止我的代码

为了实现这一点,我制作了以下代码

my.df2 <- my.df %>% mutate(across(.cols=everything(),
                                  .funs=str_replace_all(.,
                                                        substr(cur_column(),
                                                               nchar(cur_column()-2),
                                                               nchar(cur_column()-2)
                                                              ),
                                                        "R")
                                  )
                           )

不幸的是,生成的数据帧 my.df2 看起来与 my.df 完全一样,并且没有字符替换发生了。虽然没有返回错误。

我已经通过以下方式测试了 str_replace_all() 方法,它适用于向量。我想我 missing/not 理解 str_replace_all()mutate(across())[ 中的解释方式=48=]函数。

first.column <- c("CC","CT","CC")

first.column <- str_replace_all(first.column,
                                substr(colnames(my.df)[1],
                                       nchar(colnames(my.df)[1])-2,
                                       nchar(colnames(my.df)[1])-2
                                       ),
                                "R")
print(first.column)
# [1] "RR" "RT" "RR"

我 运行 不知道什么可能不起作用。我对 R 及其功能的理解不是很透彻,所以如果我遗漏了一些简单的东西,我深表歉意。我也搜索过类似的问题,但无济于事。

您可以使用 Map :

my.df[] <- Map(function(x, y) gsub(y, 'R', x), my.df, 
      substring(names(my.df), nchar(names(my.df)) - 2,nchar(names(my.df)) - 2))

my.df
#  col1_A.C col2_A.T col3_C.G
31       RR       TT       GG
#2       RC       RT       RG
#3       CC       TT       RG

使用@thelatemail 的 chartr 技巧与 purrr 中的 imap_dfc :

purrr::imap_dfc(my.df, ~chartr(substr(.y, nchar(.y)-2, nchar(.y)-2), 'R', .x))

同样可以通过首先将数据从宽格式转换为长格式来实现:

library(tidyverse)

my.df %>%
  gather(colx, rowx) %>%
  mutate(rowx = str_replace_all(rowx, substring(colx, nchar(colx) - 2, nchar(colx) - 
                  2), "R")) %>%
  group_by(colx) %>% 
  mutate(id = row_number()) %>%
  pivot_wider(names_from = colx, values_from = rowx)

我认为您只需要波浪号 ~,并使用 .fns 而不是 .funs

my.df %>% 
  mutate(
    across(
      .cols = everything(),
      .fns = ~ str_replace_all(
        string = ..1, 
        pattern = str_sub(cur_column(), nchar(cur_column()) - 2, nchar(cur_column()) - 2), 
        replacement = "R"
      )
    )
  )