I'm wondering whether there is a clean way to round values differently based on row conditions. An example of the dataset I'm using is below where I want to round columns col1
, col2
, col3
and col4
based on var
. For example, I want to round to 2 decimal places unless var
equals var1|var2|var3
where I want to round to 3 decimal places instead. Is this doable? Thanks.
set.seed(10)
dat <- data.frame(
vel = rep(c("slo", "med", "fas"), each = 28),
var = rep(paste0("var", 1:7), times = 12),
col1 = rnorm(84, 0.03, 0.08),
col2 = rnorm(84, 0.03, 0.08),
col3 = rnorm(84, 0.03, 0.08),
col4 = rnorm(84, 0.03, 0.08)
)
CodePudding user response:
library(tidyverse)
dat %>%
rowwise() %>%
mutate(across(col1:col4, ~ case_when(
var %in% c("var1", "var2", "var3") ~ round(.x, 3),
TRUE ~ round(.x, 2)
)))
# A tibble: 84 x 6
# Rowwise:
vel var col1 col2 col3 col4
<chr> <chr> <dbl> <dbl> <dbl> <dbl>
1 slo var1 0.031 0.065 0.045 -0.087
2 slo var2 0.015 0.043 -0.085 -0.042
3 slo var3 -0.08 0.083 -0.061 -0.024
4 slo var4 -0.02 0.21 0 0.12
5 slo var5 0.05 -0.06 0.04 -0.03
6 slo var6 0.06 0.02 0.11 -0.06
7 slo var7 -0.07 0 -0.02 -0.06
8 slo var1 0.001 0.015 0.132 -0.051
9 slo var2 -0.1 0.036 0.048 0.063
10 slo var3 0.009 0.122 0.005 0.068
# ... with 74 more rows
CodePudding user response:
Yes, the digits
parameter is vectorized which makes this easy.
dat[, paste0(names(dat)[-(1:2)], "rounded")] <-
lapply(dat[, -(1:2)], round,
digits = ifelse(dat$var %in% c("var1", "var2", "var3"), 3, 2))
CodePudding user response:
We can use across
to specify all columns that starts_with
the string "col" for rounding, and use ifelse
to choose which row to round
. Since the condition in each row is different, we need to include rowwise
at the start of the piping chain.
library(dplyr)
dat %>%
rowwise() %>%
mutate(across(starts_with("col"),
~ifelse(var %in% c("var1", "var2", "var3"),
round(.x, digits = 3),
round(.x, digits = 2)))) %>%
ungroup()
# A tibble: 84 × 6
vel var col1 col2 col3 col4
<chr> <chr> <dbl> <dbl> <dbl> <dbl>
1 slo var1 0.031 0.065 0.045 -0.087
2 slo var2 0.015 0.043 -0.085 -0.042
3 slo var3 -0.08 0.083 -0.061 -0.024
4 slo var4 -0.02 0.21 0 0.12
5 slo var5 0.05 -0.06 0.04 -0.03
6 slo var6 0.06 0.02 0.11 -0.06
7 slo var7 -0.07 0 -0.02 -0.06
8 slo var1 0.001 0.015 0.132 -0.051
9 slo var2 -0.1 0.036 0.048 0.063
10 slo var3 0.009 0.122 0.005 0.068
# … with 74 more rows
CodePudding user response:
For this specific case
iii=dat$var %in% c("var1","var2","var3")
ccc=grepl("col",colnames(dat))
dat[iii,ccc]=round(dat[iii,ccc],3)
dat[!iii,ccc]=round(dat[!iii,ccc],2)