Предполагая, что столбцы имеют значение list
из vector
, OP получил предупреждение, так как имеется более одного элемента или length
больше 1. Вместо if/else
мы можем использовать ifelse
или if_else
или case_when
в mutate_all
(так как нам нужно изменить все столбцы) и цикл по list
с map
library(tidyverse)
out <- df %>%
mutate_all(funs(map(., ~ case_when(.x < 6 ~ 6,
.x > 8 ~ 8,
TRUE ~ as.numeric(.x)))))
out
# w x y
#1 6, 6 6, 6 6, 8
#2 6, 6, 6 6, 8, 8 7, 8, 8
#3 6, 6, 8, 8 6, 8, 8, 8 8, 8, 8, 8
Или используя pmin/pmax
df %>%
mutate_all(funs(map(., ~pmax(.x, 6) %>%
pmin(8))))
# w x y
#1 6, 6 6, 6 6, 8
#2 6, 6, 6 6, 8, 8 7, 8, 8
#3 6, 6, 8, 8 6, 8, 8, 8 8, 8, 8, 8
Вместо применения функции к каждому из вложенных list
, мы могли бы unlist
это и позже relist
вернуться к исходному structure
df %>%
mutate_all(funs(relist(pmin(pmax(unlist(.), 6), 8), skeleton = .)))
или та же логика в base R
df[] <- lapply(df, function(x) relist(pmin(pmax(unlist(x), 6), 8), skeleton = x))
или в data.table
library(data.table)
setDT(df)[, lapply(.SD, function(x) relist(pmin(pmax(unlist(x), 6), 8),
skeleton = x))]
Тесты
Создан немного больший набор данных путем репликации строк 'df'
df1 <- df[rep(seq_len(nrow(df)), 5000),]
system.time({
df1 %>%
mutate_all(funs(map(., ~pmax(.x, 6) %>%
pmin(8))))
})
# user system elapsed
# 6.116 0.017 6.159
system.time({
df1 %>%
mutate_all(funs(relist(pmin(pmax(unlist(.), 6), 8), skeleton = .)))
})
# user system elapsed
# 0.389 0.000 0.389
Методы data.table
и lapply
(base R
) также по времени аналогичны методам с dplyr
с использованием модифицированного кода с relist