Dalším možným řešením je použít napříč() a ifelse(), např. pokud je hodnota ve sloupci x je méně než čtyři, proveďte mutace:
library(tidyverse)
tibble(x = c(1:2, 4:5), y = 1:4) %>%
mutate(across(everything(), ~ ifelse(x < 4, -.x, .x)))
#> # A tibble: 4 × 2
#> x y
#> <int> <int>
#> 1 -1 -1
#> 2 -2 -2
#> 3 4 3
#> 4 5 4
Vytvořen na 2021-11-24 do reprex balíček (v2.0.1)
Můžete také hnízdo ifelse je dohromady, např. pokud je hodnota ve sloupci x je méně než 4, nebo pokud se hodnota v každém sloupci je rovna 3, mutovat:
library(tidyverse)
tibble(x = c(1:2, 4:5), y = 1:4) %>%
mutate(across(everything(), ~ ifelse(x < 4, -.x,
ifelse(.x == 3, .x + 10, .x))))
#> # A tibble: 4 × 2
#> x y
#> <int> <dbl>
#> 1 -1 -1
#> 2 -2 -2
#> 3 4 13
#> 4 5 4
Vytvořen na 2021-11-24 do reprex balíček (v2.0.1)
A tak dále:
library(tidyverse)
tibble(x = c(1:2, 4:5), y = 1:4) %>%
mutate(across(everything(), ~ ifelse(x < 4, -.x,
ifelse(.x == 3, .x + 10,
ifelse(.x >= 5, "outlier", .x)))))
#> # A tibble: 4 × 2
#> x y
#> <chr> <dbl>
#> 1 -1 -1
#> 2 -2 -2
#> 3 4 13
#> 4 outlier 4
Vytvořen na 2021-11-24 do reprex balíček (v2.0.1)
--
Udělat mutace efektivněji, nepoužívejte dplyr::mutovat. Na ifelse() funkce je vektorizována (více informací: https://swcarpentry.github.io/r-novice-gapminder/09-vectorization/) a pokud máte velké datovém, ifelse sám bude velmi pravděpodobně rychlejší než tidyverse funkce, např.
library(tidyverse)
df <- tibble(x = c(1:2, 4:5), y = 1:4)
df$y <- ifelse(df$x < 4, -df$y, df$y)
df
#> # A tibble: 4 × 2
#> x y
#> <int> <int>
#> 1 1 -1
#> 2 2 -2
#> 3 4 3
#> 4 5 4
Edit
Další potenciální možností je nahradit hodnoty prostřednictvím zadání: df$y[df$x < 4] <- -(df$y); df$x[df$x < 4] <- -(df$x)
(rychle, ale tam jsou omezení).
Zde je rychlý srovnání navrhovaných metod s 1 milion řádků:
library(tidyverse)
df <- tibble(x = sample(1:10, 1000000, replace = TRUE),
y = sample(1:10, 1000000, replace = TRUE))
mutate_func <- function(df){
df %>%
mutate(across(everything(), ~ ifelse(x < 4, -.x, .x)))
}
ifelse_func <- function(df){
df$y <- ifelse(df$x < 4, -df$y, df$y)
}
replacement_func <- function(df) {
df$y[df$x < 4] <- -(df$y)
df$x[df$x < 4] <- -(df$x)
}
mutate_when_func <- function(df) {
mutate_when <- function(.data, when, ...) {
dots <- enquos(...)
names <- names(dots)
mutate(.data, {
test <- {{ when }}
changed <- data.frame(!!!dots, stringsAsFactors = FALSE)
out <- across(all_of(names))
# assuming `changed` and `out` have the same data frame type
out[test, ] <- changed[test, ]
out
})
}
df %>%
mutate_when(x < 4, x = -x, y = -y)
}
library(microbenchmark)
result <- microbenchmark(mutate_func(df), ifelse_func(df),
mutate_when_func(df), replacement_func(df),
times = 10)
autoplot(result)