3
data=data.frame("x1"=c(1:10),
                "x2"=c(1:4,4,6:10),
                "x3"=c(1:3,2:5,5:7),
                "x4"=c(21:30),
                "x5"=c(35:44))

recode=c("x1","x2","x3")


data <- data[recode %in% c(4,5)] <- NA

I want to store a specific set of variables for example above I store x1,x2,x3 in 'recode'. Then I want to change all the values for all variables in recode such that any value of 4 or 5 is set to NA.

bvowe
  • 3,004
  • 3
  • 16
  • 33
  • data[data[,recode] %in% c(5,6),recode] <- NA – bvowe Oct 02 '19 at 17:44
  • `%in%` doesn't wok on data.frame. It works on `vector`s – akrun Oct 02 '19 at 17:44
  • thank you, i was going to ask why that doesn't work. so i could just do that for all variables in recode... – bvowe Oct 02 '19 at 17:45
  • If you look at the `?"%in%"`, it is based on `match` and `table - vector or NULL: the values to be matched against. Long vectors are not supported.` – akrun Oct 02 '19 at 17:47

3 Answers3

2

We need to use replace with lapply

data[recode] <- lapply(data[recode], function(x) replace(x, x %in% 4:5, NA))
data
#   x1 x2 x3 x4 x5
#1   1  1  1 21 35
#2   2  2  2 22 36
#3   3  3  3 23 37
#4  NA NA  2 24 38
#5  NA NA  3 25 39
#6   6  6 NA 26 40
#7   7  7 NA 27 41
#8   8  8 NA 28 42
#9   9  9  6 29 43
#10 10 10  7 30 44

Or with dplyr

library(dplyr)
data %>%
   mutate_at(vars(recode), ~ na_if(., 4)) %>%
   mutate_at(vars(recode), ~ na_if(., 5))
#   x1 x2 x3 x4 x5
#1   1  1  1 21 35
#2   2  2  2 22 36
#3   3  3  3 23 37
#4  NA NA  2 24 38
#5  NA NA  3 25 39
#6   6  6 NA 26 40
#7   7  7 NA 27 41
#8   8  8 NA 28 42
#9   9  9  6 29 43
#10 10 10  7 30 44
akrun
  • 874,273
  • 37
  • 540
  • 662
  • @akrun; when I use lapply it converts my dataframe into a list. is there a way to not have that happen? – bvowe Oct 02 '19 at 19:40
  • @bvowe If you look at the `data[recode] <- `, we are assigning the `list` output to the columns of dataset to have the same structure as that of the dataset. But, if you only check the results of `list`, it is a list, and it can be converted to `data.frame` by wrapping `data.frame(lapply(data[recode], function(x) replace(x, x %in% 4:5, NA)))` if the intention is not to update the original data – akrun Oct 02 '19 at 19:41
1

One dplyr possibility could be:

data %>%
 mutate_at(vars(recode), ~ replace(., . %in% 4:5, NA))

   x1 x2 x3 x4 x5
1   1  1  1 21 35
2   2  2  2 22 36
3   3  3  3 23 37
4  NA NA NA 24 38
5  NA NA NA 25 39
6   6  6  4 26 40
7   7  7  5 27 41
8   8  8  5 28 42
9   9  9  6 29 43
10 10 10  7 30 44
tmfmnk
  • 38,881
  • 4
  • 47
  • 67
0

Use Map().

data[recode] <- Map(function(x) ifelse(x %in% c(4, 5), NA, x), data[recode])
data
#    x1 x2 x3 x4 x5
# 1   1  1  1 21 35
# 2   2  2  2 22 36
# 3   3  3  3 23 37
# 4  NA NA  2 24 38
# 5  NA NA  3 25 39
# 6   6  6 NA 26 40
# 7   7  7 NA 27 41
# 8   8  8 NA 28 42
# 9   9  9  6 29 43
# 10 10 10  7 30 44
jay.sf
  • 60,139
  • 8
  • 53
  • 110