How to swap TRUE and FALSE in a dataframe with dplyr - r

I'm looking to change values into their opposite (T becomes F, and vice versa) in specific rows in a column in a datatable
I know that x <- !x works for T/F variables but how to finish this dplyr approach:
library(dplyr)
library(datatable)
library(magrittr)
mtcars$selected <- T
mtcars %>% select(selected) %>% slice(c(1,4,5)) %>% mutate(??)

If you just want to subset those rows, then #Shree's answer is likely right. If you want to invert just those rows but otherwise keep all, then something like:
In dplyr:
library(dplyr)
mtcars %>%
mutate(selected = TRUE) %>%
# the heart of the answer
mutate(selected = if_else(row_number() %in% c(1, 4, 5), !selected, selected))
# mpg cyl disp hp drat wt qsec vs am gear carb selected
# 1 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4 FALSE
# 2 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4 TRUE
# 3 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1 TRUE
# 4 21.4 6 258.0 110 3.08 3.215 19.44 1 0 3 1 FALSE
# 5 18.7 8 360.0 175 3.15 3.440 17.02 0 0 3 2 FALSE
# 6 18.1 6 225.0 105 2.76 3.460 20.22 1 0 3 1 TRUE
# 7 14.3 8 360.0 245 3.21 3.570 15.84 0 0 3 4 TRUE
# 8 24.4 4 146.7 62 3.69 3.190 20.00 1 0 4 2 TRUE
# ...
You said datatable, I think you meant data.table, in which case
library(data.table)
DT <- as.data.table(mtcars)
DT[, selected := TRUE]
DT[, selected := ifelse(.I %in% c(1, 3, 4), !selected, selected)]
head(DT, n = 8)
# mpg cyl disp hp drat wt qsec vs am gear carb selected
# 1: 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4 FALSE
# 2: 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4 TRUE
# 3: 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1 FALSE
# 4: 21.4 6 258.0 110 3.08 3.215 19.44 1 0 3 1 FALSE
# 5: 18.7 8 360.0 175 3.15 3.440 17.02 0 0 3 2 TRUE
# 6: 18.1 6 225.0 105 2.76 3.460 20.22 1 0 3 1 TRUE
# 7: 14.3 8 360.0 245 3.21 3.570 15.84 0 0 3 4 TRUE
# 8: 24.4 4 146.7 62 3.69 3.190 20.00 1 0 4 2 TRUE
Or pipe-wise as
library(magrittr)
DT <- as.data.table(mtcars)
DT %>%
.[, selected := TRUE] %>%
.[, selected := ifelse(.I %in% c(1, 3, 4), !selected, selected)]
head(DT, n = 8)
# mpg cyl disp hp drat wt qsec vs am gear carb selected
# 1: 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4 FALSE
# 2: 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4 TRUE
# 3: 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1 FALSE
# 4: 21.4 6 258.0 110 3.08 3.215 19.44 1 0 3 1 FALSE
# 5: 18.7 8 360.0 175 3.15 3.440 17.02 0 0 3 2 TRUE
# 6: 18.1 6 225.0 105 2.76 3.460 20.22 1 0 3 1 TRUE
# 7: 14.3 8 360.0 245 3.21 3.570 15.84 0 0 3 4 TRUE
# 8: 24.4 4 146.7 62 3.69 3.190 20.00 1 0 4 2 TRUE
In Base R, you can do it this way:
mtcars$selected <- TRUE
mtcars$selected[c(1, 3, 4)] <- !mtcars$selected[c(1, 3, 4)]
head(mtcars, n = 8)
# mpg cyl disp hp drat wt qsec vs am gear carb selected
# Mazda RX4 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4 FALSE
# Mazda RX4 Wag 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4 TRUE
# Datsun 710 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1 FALSE
# Hornet 4 Drive 21.4 6 258.0 110 3.08 3.215 19.44 1 0 3 1 FALSE
# Hornet Sportabout 18.7 8 360.0 175 3.15 3.440 17.02 0 0 3 2 TRUE
# Valiant 18.1 6 225.0 105 2.76 3.460 20.22 1 0 3 1 TRUE
# Duster 360 14.3 8 360.0 245 3.21 3.570 15.84 0 0 3 4 TRUE
# Merc 240D 24.4 4 146.7 62 3.69 3.190 20.00 1 0 4 2 TRUE

Here's one way -
mtcars %>%
select(selected) %>%
slice(c(1,4,5)) %>%
mutate(
selected = !selected # or as.logical(1 - selected)
)

Related

Vectorized function for dplyr::mutate()

I am trying to write a vectorized function to compare a string to a vector of regular expressions and return TRUE if the string matches any of the regular expressions. The function should work on a single string, a vector of strings, and within dplyr::mutate. I'm having trouble vectorizing the function. In the below reprex, the function I would like to vectorize is is_favorite. I came up with work-arounds using base::Vectorize and purrr::map but these quite accomplish the goal. I also tried using stringi::stri_detect_regex instead of stringr::str_detect which produced the same results.
Thank you so much for your help!
library(dplyr)
library(tibble)
library(stringr)
favorite_cars <- c("^Merc", "Firebird$")
mtcars <-
mtcars %>%
tibble::rownames_to_column("car")
is_favorite <- function(x) {
any(stringr::str_detect(x, favorite_cars))
}
# Success: Works on single string
is_favorite("Merc 240D")
#> [1] TRUE
is_favorite("Ferrari Dino")
#> [1] FALSE
# Failure: On vector, returns a single boolean instead of a vector of booleans
is_favorite(mtcars$car)
#> [1] TRUE
# Failure: Add column with single boolean instead of vectorized rowwise
mtcars %>%
mutate(fav_car = is_favorite(car)) %>%
head()
#> car mpg cyl disp hp drat wt qsec vs am gear carb fav_car
#> 1 Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4 TRUE
#> 2 Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4 TRUE
#> 3 Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1 TRUE
#> 4 Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1 TRUE
#> 5 Hornet Sportabout 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2 TRUE
#> 6 Valiant 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1 TRUE
# Success...but not ideal
# https://community.rstudio.com/t/vectorise-text-function-for-dplyr-mutate/53387/2
# https://deanattali.com/blog/mutate-non-vectorized/
# https://www.jimhester.com/post/2018-04-12-vectorize/
v_is_favorite <- Vectorize(is_favorite)
mtcars %>%
mutate(fav_car = v_is_favorite(car)) %>%
head()
#> car mpg cyl disp hp drat wt qsec vs am gear carb fav_car
#> 1 Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4 FALSE
#> 2 Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4 FALSE
#> 3 Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1 FALSE
#> 4 Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1 FALSE
#> 5 Hornet Sportabout 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2 FALSE
#> 6 Valiant 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1 FALSE
# Success...better but still not ideal
# https://www.jimhester.com/post/2018-04-12-vectorize/
# http://yoshidk6.hatenablog.com/entry/2018/09/05/222248
mtcars %>%
mutate(fav_car = purrr::map_lgl(car, is_favorite)) %>%
head()
#> car mpg cyl disp hp drat wt qsec vs am gear carb fav_car
#> 1 Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4 FALSE
#> 2 Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4 FALSE
#> 3 Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1 FALSE
#> 4 Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1 FALSE
#> 5 Hornet Sportabout 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2 FALSE
#> 6 Valiant 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1 FALSE
Created on 2020-08-28 by the reprex package (v0.3.0)
I also consulted the following resources:
https://adv-r.hadley.nz/perf-improve.html#vectorise
https://deanattali.com/blog/mutate-non-vectorized/
https://www.jimhester.com/post/2018-04-12-vectorize/
https://community.rstudio.com/t/vectorise-text-function-for-dplyr-mutate/53387/2
http://yoshidk6.hatenablog.com/entry/2018/09/05/222248
https://dplyr.tidyverse.org/articles/programming.html
any would always return only one logical value as output. You should collapse your favorite_cars regex as length 1 string.
is_favorite <- function(x) {
stringr::str_detect(x, paste0(favorite_cars, collapse = "|"))
#Will also work with base R grepl
#grepl(paste0(favorite_cars, collapse = "|"), x)
}
and then use :
library(dplyr)
mtcars %>% mutate(fav_car = is_favorite(car))
# car mpg cyl disp hp drat wt qsec vs am gear carb fav_car
#1 Mazda RX4 21.0 6 160.0 110 3.90 2.62 16.5 0 1 4 4 FALSE
#2 Mazda RX4 Wag 21.0 6 160.0 110 3.90 2.88 17.0 0 1 4 4 FALSE
#3 Datsun 710 22.8 4 108.0 93 3.85 2.32 18.6 1 1 4 1 FALSE
#4 Hornet 4 Drive 21.4 6 258.0 110 3.08 3.21 19.4 1 0 3 1 FALSE
#5 Hornet Sportabout 18.7 8 360.0 175 3.15 3.44 17.0 0 0 3 2 FALSE
#6 Valiant 18.1 6 225.0 105 2.76 3.46 20.2 1 0 3 1 FALSE
#7 Duster 360 14.3 8 360.0 245 3.21 3.57 15.8 0 0 3 4 FALSE
#8 Merc 240D 24.4 4 146.7 62 3.69 3.19 20.0 1 0 4 2 TRUE
#9 Merc 230 22.8 4 140.8 95 3.92 3.15 22.9 1 0 4 2 TRUE
#10 Merc 280 19.2 6 167.6 123 3.92 3.44 18.3 1 0 4 4 TRUE
#11 Merc 280C 17.8 6 167.6 123 3.92 3.44 18.9 1 0 4 4 TRUE
#...
#...
where the pattern that we are looking for becomes
paste0(favorite_cars, collapse = "|")
#[1] "^Merc|Firebird$"

`if_else` condition on multiple (dynamically specified) columns

I am trying mutate a new column based on the values of multiple existing columns, such that if any of the columns equal the specified value, if_else evaluates to TRUE. I can do this using multiple comparison expressions in if_else, however this doesn't work since I need to dynamically specify the columns using quasiquotation. Reprex with explanatory comments below.
I would appreciate any suggestions on how to evaluate a comparison on multple, dynamically specified columns.
Thank you in advance for your help!
library(dplyr)
#>
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#>
#> filter, lag
#> The following objects are masked from 'package:base':
#>
#> intersect, setdiff, setequal, union
mtcars <- head(mtcars, 8)
# Desired output, using individual comparisons for each column
mtcars %>%
mutate(color = if_else(
(gear == 4 | carb == 4),
"purple",
"green")
)
#> mpg cyl disp hp drat wt qsec vs am gear carb color
#> 1 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4 purple
#> 2 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4 purple
#> 3 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1 purple
#> 4 21.4 6 258.0 110 3.08 3.215 19.44 1 0 3 1 green
#> 5 18.7 8 360.0 175 3.15 3.440 17.02 0 0 3 2 green
#> 6 18.1 6 225.0 105 2.76 3.460 20.22 1 0 3 1 green
#> 7 14.3 8 360.0 245 3.21 3.570 15.84 0 0 3 4 purple
#> 8 24.4 4 146.7 62 3.69 3.190 20.00 1 0 4 2 purple
# Failed attempts to do comparisons on multiple columns
mtcars %>%
mutate(color = if_else(
(gear|carb == 4),
"purple",
"green")
)
#> mpg cyl disp hp drat wt qsec vs am gear carb color
#> 1 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4 purple
#> 2 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4 purple
#> 3 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1 purple
#> 4 21.4 6 258.0 110 3.08 3.215 19.44 1 0 3 1 purple
#> 5 18.7 8 360.0 175 3.15 3.440 17.02 0 0 3 2 purple
#> 6 18.1 6 225.0 105 2.76 3.460 20.22 1 0 3 1 purple
#> 7 14.3 8 360.0 245 3.21 3.570 15.84 0 0 3 4 purple
#> 8 24.4 4 146.7 62 3.69 3.190 20.00 1 0 4 2 purple
mtcars %>%
mutate(color = if_else(
(c(gear, carb) == 4),
"purple",
"green")
)
#> Error: Problem with `mutate()` input `color`.
#> x Input `color` can't be recycled to size 8.
#> ℹ Input `color` is `if_else((c(gear, carb) == 4), "purple", "green")`.
#> ℹ Input `color` must be size 8 or 1, not 16.
# Using dynamically specified columns and quasiquotation
my_vars <- c("gear", "carb")
# Quasiquotation works with `select`, and `coalesce`
mtcars %>% select(!!!syms(my_vars))
#> gear carb
#> Mazda RX4 4 4
#> Mazda RX4 Wag 4 4
#> Datsun 710 4 1
#> Hornet 4 Drive 3 1
#> Hornet Sportabout 3 2
#> Valiant 3 1
#> Duster 360 3 4
#> Merc 240D 4 2
mtcars %>% mutate(any_value = coalesce(!!!syms(my_vars)))
#> mpg cyl disp hp drat wt qsec vs am gear carb any_value
#> 1 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4 4
#> 2 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4 4
#> 3 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1 4
#> 4 21.4 6 258.0 110 3.08 3.215 19.44 1 0 3 1 3
#> 5 18.7 8 360.0 175 3.15 3.440 17.02 0 0 3 2 3
#> 6 18.1 6 225.0 105 2.76 3.460 20.22 1 0 3 1 3
#> 7 14.3 8 360.0 245 3.21 3.570 15.84 0 0 3 4 3
#> 8 24.4 4 146.7 62 3.69 3.190 20.00 1 0 4 2 4
# Desired `mutate`: if any columns (via quasiquotation) == 4, then TRUE
mtcars %>%
mutate(color = if_else(
any(!!!syms(my_vars) == 4),
"purple",
"green")
)
#> Error in splice(dot_call(capture_dots, frame_env = frame_env, named = named, : 'list' object cannot be coerced to type 'double'
Created on 2020-08-17 by the reprex package (v0.3.0)
You can subset the columns that you want to check, compare them with the value and do rowSums to count their occurence and assign value based on that.
mtcars$any_value <- ifelse(rowSums(mtcars[my_vars] == 4) > 0, 'purple', 'green')
#Without ifelse
mtcars$any_value <- c('green', 'purple')[(rowSums(mtcars[my_vars] == 4) > 0) + 1]
mtcars
# mpg cyl disp hp drat wt qsec vs am gear carb any_value
#Mazda RX4 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4 purple
#Mazda RX4 Wag 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4 purple
#Datsun 710 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1 purple
#Hornet 4 Drive 21.4 6 258.0 110 3.08 3.215 19.44 1 0 3 1 green
#Hornet Sportabout 18.7 8 360.0 175 3.15 3.440 17.02 0 0 3 2 green
#Valiant 18.1 6 225.0 105 2.76 3.460 20.22 1 0 3 1 green
#Duster 360 14.3 8 360.0 245 3.21 3.570 15.84 0 0 3 4 purple
#Merc 240D 24.4 4 146.7 62 3.69 3.190 20.00 1 0 4 2 purple
A tidyverse approach could be with rowwise and c_across
library(dplyr)
mtcars %>%
rowwise() %>%
mutate(any_value= if(any(c_across(all_of(my_vars)) == 4)) 'purple' else 'green')
mtcars %>%
mutate(
flag = eval(parse(text = str_c(my_vars, " == 4", collapse = "|"))),
color = if_else(flag, "purple", "green")
) %>%
select(-flag)

Using dplyr, how should I create a column of strings repeating a character based on the value of another column?

With mtcars for example, I'd like to create a new column carb_dots such that when carb = 4, carb_dots = "...."
Using dplyr, I've tried
library(dplyr)
mtcars2 <- mtcars %>% mutate(carb_dots = rep(".", carb))
This errors with
Error in mutate_impl(.data, dots) :
Evaluation error: invalid 'times' argument.
What should I do? Thanks for your suggestions.
With the addition of stringr, you can do:
mtcars %>%
mutate(carb_dots = str_dup(".", carb))
mpg cyl disp hp drat wt qsec vs am gear carb carb_dots
1 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4 ....
2 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4 ....
3 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1 .
4 21.4 6 258.0 110 3.08 3.215 19.44 1 0 3 1 .
5 18.7 8 360.0 175 3.15 3.440 17.02 0 0 3 2 ..
6 18.1 6 225.0 105 2.76 3.460 20.22 1 0 3 1 .
7 14.3 8 360.0 245 3.21 3.570 15.84 0 0 3 4 ....
8 24.4 4 146.7 62 3.69 3.190 20.00 1 0 4 2 ..
9 22.8 4 140.8 95 3.92 3.150 22.90 1 0 4 2 ..
10 19.2 6 167.6 123 3.92 3.440 18.30 1 0 4 4 ....
We can use strrep
library(dplyr)
mtcars %>%
mutate(carb_dots = strrep(".", carb))
# mpg cyl disp hp drat wt qsec vs am gear carb carb_dots
#Mazda RX4 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4 ....
#Mazda RX4 Wag 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4 ....
#Datsun 710 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1 .
#Hornet 4 Drive 21.4 6 258.0 110 3.08 3.215 19.44 1 0 3 1 .
#Hornet Sportabout 18.7 8 360.0 175 3.15 3.440 17.02 0 0 3 2 ..
#Valiant 18.1 6 225.0 105 2.76 3.460 20.22 1 0 3 1 .
#Duster 360 14.3 8 360.0 245 3.21 3.570 15.84 0 0 3 4 ....
#...
If we need to use rep
mtcars %>%
rowwise %>%
mutate(carb_dots = paste(rep(".", carb), collapse=""))

mutate with case_when - multiple LHS/RHS OR evaluations

I'm not sure of the best way to ask this question.
I would like to mutate using case_when (or if_else if that works better) to examine if a value exists in any of a range of columns.
E.g. in mtcars I would like to check if any of the columns vs, am, gear or carb contained 1 or 2 and set a new variable newVar to 1 if they do. I could do the following:
mtcars %>%
mutate(newVar = case_when(vs %in% c(1, 2) | am %in% c(1, 2) | gear %in% c(1, 2) | carb %in% c(1, 2) ~ 1,
TRUE ~ 0))
Is there a prettier way to do this? I want to check across 10+ columns so it gets long. Something like:
mtcars %>%
mutate(newVar = case_when(c(vs, am, gear, carb) %in% c(1, 2) ~ 1,
TRUE ~ 0))
I think base R can work good here. Select columns for which you want to check and take row wise sum of logical vector to calculate newVar.
df <- mtcars
cols <- c("vs", "am", "gear", "carb")
df$newVar <- +(rowSums(df[cols] == 1 | df[cols] == 2) > 0)
df
# mpg cyl disp hp drat wt qsec vs am gear carb newVar
#Mazda RX4 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4 1
#Mazda RX4 Wag 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4 1
#Datsun 710 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1 1
#Hornet 4 Drive 21.4 6 258.0 110 3.08 3.215 19.44 1 0 3 1 1
#Hornet Sportabout 18.7 8 360.0 175 3.15 3.440 17.02 0 0 3 2 1
#Valiant 18.1 6 225.0 105 2.76 3.460 20.22 1 0 3 1 1
#Duster 360 14.3 8 360.0 245 3.21 3.570 15.84 0 0 3 4 0
#Merc 240D 24.4 4 146.7 62 3.69 3.190 20.00 1 0 4 2 1
#Merc 230 22.8 4 140.8 95 3.92 3.150 22.90 1 0 4 2 1
#Merc 280 19.2 6 167.6 123 3.92 3.440 18.30 1 0 4 4 1
#....
We can also use apply for row-wise manipulation
df$newVar <- +(apply(df[cols] == 1 | df[cols] == 2, 1, any))
We can use tidyverse option to create the column
library(dplyr)
library(purrr)
mtcars %>%
mutate(newVar = select(., vs:carb) %>%
map(~ .x %in% 1:2) %>%
reduce(`|`) %>%
as.integer)
#. mpg cyl disp hp drat wt qsec vs am gear carb newVar
#1 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4 1
#2 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4 1
#3 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1 1
#4 21.4 6 258.0 110 3.08 3.215 19.44 1 0 3 1 1
#5 18.7 8 360.0 175 3.15 3.440 17.02 0 0 3 2 1
#6 18.1 6 225.0 105 2.76 3.460 20.22 1 0 3 1 1
#7 14.3 8 360.0 245 3.21 3.570 15.84 0 0 3 4 0
#8 24.4 4 146.7 62 3.69 3.190 20.00 1 0 4 2 1
# ...
Or with base R
nm1 <- c("vs", "am", "gear", "carb")
mtcars$newVar <- +(Reduce(`|`, lapply(mtcars[nm1], `%in%`, 1:2)))

Adding row in dplyr across a selected number of columns

While within dplyr workflow I would like to append a row across a selected number of columns.
Desired results
Starting with the mtcarsdata and applying function(s) with the goal of adding string "A" to columns 2:5 the one should arrive at the following results:
mpg cyl disp hp drat wt qsec vs am gear carb
NA A A A A NA NA NA NA NA NA
Mazda RX4 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4
Mazda RX4 Wag 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4
Datsun 710 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1
Hornet 4 Drive 21.4 6 258.0 110 3.08 3.215 19.44 1 0 3 1
Hornet Sportabout 18.7 8 360.0 175 3.15 3.440 17.02 0 0 3 2
Valiant 18.1 6 225.0 105 2.76 3.460 20.22 1 0 3 1
Duster 360 14.3 8 360.0 245 3.21 3.570 15.84 0 0 3 4
Merc 240D 24.4 4 146.7 62 3.69 3.190 20.00 1 0 4 2
Merc 230 22.8 4 140.8 95 3.92 3.150 22.90 1 0 4 2
The following criteria were met:
For the columns with available index in vars() call the "A" string was added
For the remaining columns the NA value was provided
Approach
require(dplyr)
mtcars %>%
mutate_at(.cols = vars(2:5),
.funs = add_row(. = "A", .before = 1))
Naturally, this results in an error message:
Error: Unsupported index type: NULL
Hence my question: how can I utilise add_row, or a similar approach, to force value across a set of columns initially passed via vars()?
Side notes
I don't mind doing this via rbind but I would like to keep my %>% workflow:
%>% - receive object
Add something across first row to columns x:y %>%
Add something across first row to columns m:n %>%
Other manipulations
Add the row then update:
mtcars %>%
head %>%
add_row(.before = 1) %>%
mutate_at(.cols = vars(2:5),
funs(ifelse(is.na(.), "A", .)))
# mpg cyl disp hp drat wt qsec vs am gear carb
# 1 NA A A A A NA NA NA NA NA NA
# 2 21.0 6 160 110 3.9 2.620 16.46 0 1 4 4
# 3 21.0 6 160 110 3.9 2.875 17.02 0 1 4 4
# 4 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1
# 5 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1
# 6 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2
# 7 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1
Note: This will add "A" to any row that has NAs.

Resources