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)
