Q:

Is there a way to subset a dataframe against a logical dataframe and preserve the original dataframe structure in R?

I have been wrangling some unstructured text and I have separated phrases into separate fields, primarily for readability purposes. The resulting data frame looks something like this (i.e. it contains NAs):
behaviour <- data.frame(field_1 = c("cat eats meal", "cat watches fish", "cat watches frog", NA),
                        field_2 = c("bird flies away", "cat watches bird", "cat watches fish", NA),
                        field_3 = c("cat is bored", NA, NA, "cat watches sky"))

I'm now interested in extracting all the values that contain the word "watches" whilst preserving the structure of the dataset.  
watches <- behaviour %>%
  map_df(~ str_detect(., "watches"))

The two datasets look like this:  
behaviour

 
watches

I would like to obtain a new data frame where the values in behaviour are kept only if the corresponding values in watches are TRUE, and the structure of the original data frame is preserved. I tried converting both to a matrix and subsetting via behaviour[watches] but the output was a character vector that did not have a preserved structure. 

I'm wondering now if this somehow involves a mutate_all on behaviour i.e. if  watches == T, then paste or keep the original value in behaviour?     
Thanks in advance!  

A:

Since you already have watches you can directly assign NA : 
behaviour[!watches] <- NA

Without creating watches we can use mutate_all as : 
library(dplyr)
behaviour %>% mutate_all(~replace(., !stringr::str_detect(., "watches"), NA))

#           field_1          field_2         field_3
#1             <NA>             <NA>            <NA>
#2 cat watches fish cat watches bird            <NA>
#3 cat watches frog cat watches fish            <NA>
#4             <NA>             <NA> cat watches sky

In base R, we can use lapply with grepl 
behaviour[] <- lapply(behaviour, function(x) replace(x, !grepl('watches', x), NA))
#or with grep
#behaviour[] <- lapply(behaviour, function(x) replace(x, -grep('watches', x), NA))

