0

I have the following dataframe

v    w    e   
dog  cat  -> 
frog cat  -> 
frog dog  -> 
frog fish ->
fish cat  -> 

This is the function I wrote. It will output an updated dataframe based on the user input. The inputs V, W, and E can be a single string or a list. But V, W, and E must have the same length.

convert_df <- function(df, V, W, E) {
  df %>%
    dplyr::mutate(flag = (v %in% V & w %in% W | w %in% V & v %in% W),
                  txt = ifelse(flag, paste(V,E,W), paste(v,e,w)))
}

For example, this would be my expected output for the following. As you can see I want to change the txt column dog <-> frog and cat <-> dog :

> V <- c('dog', 'cat')
> W <- c('frog', 'dog')
> E <- c('<->', '<->')
> convert_df(df,V,W,E)

v    w    e   
dog  cat  <-> 
frog cat  -> 
frog dog  <-> 
frog fish ->
fish cat  -> 

However my function will output

dog  cat  <-> 
frog cat  <-> 
frog dog  <-> 
frog fish ->
fish cat  -> 

How can i fix my function? The indexes for V,W, and E are aligned to what i want to change in the dataframe. And my current function just checks if the v and w are in V and W regardless of the index alignment.

UPDATE:

Here I switch the order of V and W for the first element. I want to make my function dynamic so that the following would give the expected result as well:

> V <- c('frog', 'cat')
> W <- c('dog', 'dog')
> E <- c('<->', '<->')
> convert_df(df,V,W,E)

v    w    e   
dog  cat  <-> 
frog cat  -> 
frog dog  <-> 
frog fish ->
fish cat  -> 

1 Answer 1

1

I would probably do this with a join:

df <- tibble::tribble(
  ~v,   ~w,   ~e,   
"dog","cat", "->",
"frog","cat", "->", 
"frog","dog", "->",
"frog","fish","->",
"fish","cat", "->") 


v <- c('dog', 'frog')
w <- c('cat', 'dog')
E <- c('<->', '<->')

newdat <- do.call(data.frame, list(v=v,w=w,E=E))

df <- left_join(df, newdat) %>% 
  mutate(e = ifelse(is.na(E), e, E)) %>% 
  select(-E)


# # A tibble: 5 × 3
#    v     w     e    
# <chr> <chr> <chr>
# 1 dog   cat   <->  
# 2 frog  cat   ->   
# 3 frog  dog   <->  
# 4 frog  fish  ->   
# 5 fish  cat   ->   

  
Sign up to request clarification or add additional context in comments.

4 Comments

Is there a reason do do.call(data.frame, list(v=v,w=w,E=E)) when you can do just data.frame(v=v,w=w,E=E)?
Also, you can replace your ifelse with coalesce(E, e), a handy NA-handling function in dplyr.
I just updated my question - I also want the function to work if the inputs of v and w are swapped by the user.
@Eisen Just do a double left_join: df %>% left_join(df2, by = c("v" = "V", "w" = "W")) %>% left_join(df2, by = c("v" = "W", "w" = "V")) %>% mutate(E = coalesce(E.y, E.x, e)).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.