I have a dataframe with this structure:
id v1 v2 v3 v4 v5
1 . 1 . 2 3
2 1 2 3 . .
3 3 2 . 1 .
And I want to recode it like this
id v1 v2 v3 v4 v5
1 0 3 0 2 1
2 3 2 1 0 0
3 1 2 0 3 0
So I want to recode values (1=3) (missing = 0) (3=1)
In SPSS this is fairly intuitive:
recode v1 to v5 (sysmis=0)(3=1)(1=3)(else=copy).
I'm looking for a similar approach in R. No preference on either base or tidyverse aproach.
CodePudding user response:
Replace the .
to NA
, convert the type of columns (type.convert
) to numeric, subtract from 4 and replace the NA
with 0
df[df == "."] <- NA
df <- type.convert(df, as.is = TRUE)
df[-1] <- 4- df[-1]
df[is.na(df)] <- 0
Or using tidyverse
library(dplyr)
library(tidyr)
df %>%
mutate(across(-id, ~ replace_na(4 - as.numeric(.x), 0)))
-output
id v1 v2 v3 v4 v5
1 1 0 3 0 2 1
2 2 3 2 1 0 0
3 3 1 2 0 3 0
-output
> df
id v1 v2 v3 v4 v5
1 1 0 3 0 2 1
2 2 3 2 1 0 0
3 3 1 2 0 3 0
data
df <- structure(list(id = 1:3, v1 = c(".", "1", "3"), v2 = c(1L, 2L,
2L), v3 = c(".", "3", "."), v4 = c("2", ".", "1"), v5 = c("3",
".", ".")), class = "data.frame", row.names = c(NA, -3L))
CodePudding user response:
This was surprisingly difficult with recode
, but it is I think a more readable answer:
library(dplyr)
dat %>%
mutate(across(v1:v5, ~ .x %>%
replace(. == ".", 0) %>%
as.numeric() %>%
recode(`3` = 1, `1` = 3)
))
id v1 v2 v3 v4 v5
1 1 0 3 0 2 1
2 2 3 2 1 0 0
3 3 1 2 0 3 0