nullepart
nullepart

Reputation: 165

How to assign a value to a data.frame filtered by dplyr?

I am trying to modify a data.frame filtered by dplyr but I don't quite seem to grasp what I need to do. In the following example, I am trying to filter the data frame z and then assign a new value to the third column -- I give two examples, one with "9" and one with "NA".

require(dplyr)
z <- data.frame(w = c("a", "a", "a", "b", "c"), x = 1:5, y = c("a", "b", "c", "d", "e"))
z %>% filter(w == "a" & x == 2) %>% select(y) 
z %>% filter(w == "a" & x == 2) %>% select(y) <- 9 # Should be similar to z[z$w == "a" & z$ x == 2, 3] <- 9
z %>% filter(w == "a" & x == 3) %>% select(y) <- NA # Should be similar to z[z$w == "a" & z$ x == 3, 3] <- NA

Yet, it doesn't work: I get the following error message:

"Error in z %>% filter(w == "a" & x == 3) %>% select(y) <- NA : impossible de trouver la fonction "%>%<-"

I know that I can use the old data.frame notation, but what would be the solution for dplyr?

Thanks!

Upvotes: 14

Views: 13099

Answers (2)

eipi10
eipi10

Reputation: 93811

Filtering will subset the data frame. If you want to keep the whole data frame, but modify part of it, you can, for example use mutate with ifelse. I've added stringsAsFactors=FALSE to your sample data so that y will be a character column.

z <- data.frame(w = c("a", "a", "a", "b", "c"), x = 1:5, y = c("a", "b", "c", "d", "e"), 
                stringsAsFactors=FALSE)

z %>% mutate(y = ifelse(w=="a" & x==2, 9, y))
  w x y
1 a 1 a
2 a 2 9
3 a 3 c
4 b 4 d
5 c 5 e

Or with replace:

z %>% mutate(y = replace(y, w=="a" & x==2, 9),
             y = replace(y, w=="a" & x==3, NA)) 
  w x    y
1 a 1    a
2 a 2    9
3 a 3 <NA>
4 b 4    d
5 c 5    e

Upvotes: 17

Frank
Frank

Reputation: 66819

It is my impression that the dplyr package is philosophically opposed to modifying your underlying data. You might find the data.table package friendlier for this operation:

library(data.table)
z <- data.table(w = c("a", "a", "a", "b", "c"), x = 1:5, y = c("a", "b", "c", "d", "e"))
m <- data.table(w = c("a","a"), x = c(2,3), new_y = c("9", NA))

z[m, y := new_y, on=c("w","x")]


   w x  y
1: a 1  a
2: a 2  9
3: a 3 NA
4: b 4  d
5: c 5  e

I'm sure there's a way in base R as well, but I don't know it. In particular, I can't get merge or match to do the job.

Upvotes: 7

Related Questions