#r #str-replace #dplyr #across
#r #str-заменить #dplyr #через
Вопрос:
Краткое изложение моей цели
У меня есть следующая структура фрейма данных:
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
Для каждого столбца я хочу заменить любой символ, который соответствует 3-му последнему символу имени столбца, символом «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.C, а A — 3-й последний символ. Таким образом, все буквы 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() следующим образом, и он работает с вектором. Я полагаю, тогда есть что-то, чего я не понимаю / не понимаю в том, как str_replace_all() интерпретируется в функции mutate(across()) .
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 и его функций не очень полное, поэтому я приношу извинения, если я пропустил что-то простое. Я также искал похожие вопросы, но безрезультатно.
Ответ №1:
Я думаю, вам просто нужна была тильда ~
, и использовать .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"
)
)
)
Комментарии:
1. 1, потому что он исправляет исходный код, которым я поделился. Но я сохраняю ответ Ронака как принятый, поскольку он быстрее. @Ronak ‘ # пользовательская система истекла # 0.002 0.000 0.001 ‘ CourtesyBus ‘ # пользовательская система истекла # 0.004 0.000 0.004 ‘
2. Кроме того, что делает ‘string = ..1’?
3. да, согласен, что базовое R-решение более эффективно.
..1
является заполнителем для вашей.cols
справки. вы можете использовать.x
или просто.
(как вы делали в своем исходном коде), но я предпочитаю..1
4. Работал с <.> вместо <..1>
Ответ №2:
Вы можете использовать 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
Используя chartr
трюк @thelatemail с imap_dfc
помощью from purrr
:
purrr::imap_dfc(my.df, ~chartr(substr(.y, nchar(.y)-2, nchar(.y)-2), 'R', .x))
Комментарии:
1. У меня была похожая мысль, но
chartr
вместо этого я использовал —my.df[] <- Map(chartr, my.df, old=substr(names(my.df), nchar(names(my.df))-2, nchar(names(my.df))-2), new='R')
2. Ронак, посмотрел функцию Map, поэтому, чтобы правильно понять, функция substring возвращает vector (‘A’,’A’,’C’). Итак, на первой итерации y в gsub — это ‘A’, а x — первый столбец «col1_A.C», следовательно, A заменяется на ‘R’, а на второй итерации y снова ‘A’, а x — второй столбец и так далее .. Правильно ли я понимаю?
Ответ №3:
То же самое может быть достигнуто путем первого преобразования ваших данных из широкого в длинный формат:
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)