1

I would like to add new columns into another data frame at the end of a pipe with mutate using a condition. If the length of the variable is zero, then add a dash in the column, otherwise add the content. This is part of a loop where I bind the resulting data frames, hence all lists have only one item and the data frames here only have one row.

Is it possible with mutate to add a column into a data frame other than the one being used in the pipe?

I tried solving this using tips I found here: Combine mutate with conditional values

Example code:

x <- "bbb"
y <- ""
end <- data.frame(a_col="aaa")

end <- x %>%
mutate (end, x_col = case_when(length()==0 ~ '-',
                         length()!=0 ~ .))

end <- y %>%
mutate (end, y_col = case_when(length()==0 ~ '-',
                         length()!=0 ~ .))

With both, I get this: "Error in UseMethod("mutate_") : no applicable method for 'mutate_' applied to an object of class "character""

Expected result for the 'end' data frame:

    a_col  x_col  y_col
1    aaa    bbb     -
fredibeni
  • 65
  • 7
  • Hey, in your `mutate` commands, you have the incorrect structure. You should use `x %>% mutate(x_col = case_when(length == 0 ~ '-', length() != 0 ~ .))`. Not to mention, this is not the way you should go. You may want to look at `if_else` from the `dplyr` packages. – akash87 Jul 05 '18 at 18:38
  • Thanks! Is it possible though to use mutate for adding a column to a data frame other than the one in the pipeline? – fredibeni Jul 06 '18 at 08:34

1 Answers1

2

Is this the behavior you were looking for?

x <- "bbb"
y <- ""
end <- data.frame(a_col = "aaa")

end %>% mutate(x_col = case_when(nchar(x) == 0 ~ "-",
                                 TRUE ~ x),
               y_col = case_when(nchar(y) == 0 ~ "-",
                                 TRUE ~ y))

  a_col x_col y_col
1   aaa   bbb     -

I think you want to use ?nchar() instead of ?length() so you are returned the number of characters in a string, instead of the number of elements in a vector.

The error you were getting was because you were trying to call mutate(data = "bbb"), but mutate requires the data argument to be a data.frame or at least inherit its class from data.frame. So it complained when you tried to pass it a character.

This is another way to capture multiple pipeline results in a list and them perform the empty string substitution before binding the new columns onto the existing data frame.

pipe_results <- list()

pipe_results[["x"]] <- x # these names become column names
pipe_results[["y"]] <- y

map_dfc(pipe_results,
        ~ gsub("^$", "-", .)) %>%
            bind_cols(end, .)
Nate
  • 10,361
  • 3
  • 33
  • 40
  • That is my expected output, I added it to the question together with some more explanation. Your solution works, but `x` or `y` are results of a pipeline. I wanted to add them to the separate `end` data frame with mutate at the end of their pipes. Is that possible without saving `x` and `y` and building a new pipe for adding them? Thank you – fredibeni Jul 06 '18 at 08:32
  • Sure it's possible. Do `x` and `y` come out of the same pipeline or are they separate products? – Nate Jul 06 '18 at 11:53
  • They are separate. Thank you! – fredibeni Jul 06 '18 at 14:59
  • Updated with another strategy, sorry it took me a while to get back :) – Nate Jul 07 '18 at 20:45