Reputation: 163
Code:
library(dplyr)
library(magrittr)
a = c("aa", "bb", "cc", NA, "aa")
b = c("aa", "bb", "cc", "bb", "bb")
c = c(NA, "aa", "aa", NA, "bb")
d = c(1, 1, 2, 2, 3)
df = data.frame(a,b,c,d)
cols <- c("a","b","c")
missing <- function(x) {
replace(x, ifelse(is.na(x), "Missing", ifelse(x == "aa", "Missing",x)))
}
df %<>%
mutate(across(where(is.character), missing))
I want to evaluate multiple columns in a df and change NAs or any "aa" value to "Missing". I want to create a succinct function to call but I can't figure out how to make it work as I get the following error:
Error: Problem with
mutate()
input..1
. x argument "values" is missing, with no default i Input..1
isacross(where(is.character), missing)
.
Desired Output:
a b c d
missing missing missing 1
bb bb missing 1
cc cc missing 2
missing bb missing 2
missing bb bb 3
Upvotes: 0
Views: 276
Reputation: 378
A Base R
solution is as follows:
df[df=="aa" | is.na(df)]="missing"
DATA:
a <- c("aa", "bb", "cc", NA, "aa")
b <- c("aa", "bb", "cc", "bb", "bb")
c <- c(NA, "aa", "aa", NA, "bb")
d <- c(1, 1, 2, 2, 3)
df <- data.frame(a,b,c,d)
cols <- c("a","b","c")
OUTPUT:
a b c d
1 missing missing missing 1
2 bb bb missing 1
3 cc cc missing 2
4 missing bb missing 2
5 missing bb bb 3
Upvotes: 1
Reputation: 35554
You can use na_if()
to replace "aa"
to NA
and replace_na()
to replace NA
with "missing"
.
library(dplyr)
library(tidyr)
cols <- c("a", "b", "c")
df %>%
mutate(across(cols, ~ replace_na(na_if(.x, "aa"), "missing")))
# a b c d
# 1 missing missing missing 1
# 2 bb bb missing 1
# 3 cc cc missing 2
# 4 missing bb missing 2
# 5 missing bb bb 3
You cam also use fct_explicit_na()
from forcats
.
library(forcats)
df %>%
mutate(across(cols, ~ fct_explicit_na(na_if(.x, "aa"))))
# a b c d
# 1 (Missing) (Missing) (Missing) 1
# 2 bb bb (Missing) 1
# 3 cc cc (Missing) 2
# 4 (Missing) bb (Missing) 2
# 5 (Missing) bb bb 3
Upvotes: 1
Reputation: 4151
You can use anonymous functions inside across like this
library(tidyverse)
a <- c("aa", "bb", "cc", NA, "aa")
b <- c("aa", "bb", "cc", "bb", "bb")
c <- c(NA, "aa", "aa", NA, "bb")
d <- c(1, 1, 2, 2, 3)
df <- data.frame(a,b,c,d)
cols <- c("a","b","c")
df %>%
mutate(across(.cols = where(is.character),
.fns = ~ case_when(.x %>% is.na ~ "Missing",
.x == "aa" ~ "Missing",
TRUE ~ .x)
)
)
Another option is to use a a regular function
test_function <- function(col) {
case_when(col %>% is.na() ~ "Missing",
col == "aa" ~ "Missing",
TRUE ~ col)
}
df %>%
mutate(across(.cols = where(is.character),
.fns = test_function)
)
Upvotes: 1
Reputation: 39585
Try this solution using across()
:
library(dplyr)
library(magrittr)
#Data
a = c("aa", "bb", "cc", NA, "aa")
b = c("aa", "bb", "cc", "bb", "bb")
c = c(NA, "aa", "aa", NA, "bb")
d = c(1, 1, 2, 2, 3)
df = data.frame(a,b,c,d,stringsAsFactors = F)
#Vector
cols <- c("a","b","c")
#Code
df %>%
mutate(across(cols, ~ ifelse(.=='aa' | is.na(.), 'Missing', .)))
Output:
a b c d
1 Missing Missing Missing 1
2 bb bb Missing 1
3 cc cc Missing 2
4 Missing bb Missing 2
5 Missing bb bb 3
Upvotes: 1