6

I am having problems with this ifelse sentence inside map function:

df<-list(mtcars,mtcars)

All I want to do is to organize each dataframe of this list this way:slice(x,c(n(),2:(n()-1),1))

map(df, ~   slice(.x,c(n(),2:(n()-1),1)))   # it works well. 

But I cant do this inside ifelse when I set the condition x$cyl == 4:

map(df, ~   ifelse(sum(.x$cyl == 4) > 0, slice(.x,c(n(),2:(n()-1),1)), .x)) # The output is weird

I tried to do the same using lapply but its not working:

lapply(df, function(x) ifelse(sum(x$cyl == 4) > 0, slice(x,c(n(),2:(n()-1),1)),x))

Any help?

Laura
  • 675
  • 10
  • 32
  • I saw your comments to Alec B for clarification, so I changed my answers based on the information you provided. The `map_if` function should do the trick. – www Apr 29 '21 at 01:13
  • 1
    `ifelse` is used when you are sure that all the arguments have the same length. Here, `if/else` is better. According toe documentation `Value - A vector of the same length and attributes (including dimensions and "class") as test and data values from the values of yes or no.` The 'test' is logical vector, which is correct, but is of length 1. 'yes' is a data.frame/tibble and not a vector and the number of rows are different than the 'no'. You could wrap it in a `list` to get the length 1 for 'yes', 'no'. But, I avoid using ifelse here – akrun Apr 29 '21 at 17:20

2 Answers2

5

We can use map_if to apply the function only when a condition is TRUE.

library(tidyverse)

df <- list(mtcars,mtcars)

df2 <- map_if(df, .p = function(y) any(y$cyl == 4),
                  .f = ~slice(.x, c(n(), 2:(n()-1), 1)))
www
  • 38,575
  • 12
  • 48
  • 84
3

This approach checks each data.frame in the list for any rows where cyl == 4. If it meets that condition, your desired slice is returned. Otherwise, the data.frame is returned unchanged.

library(dplyr)


df<-list(mtcars,mtcars)



lapply(df, function(x) {
  if (any(x$cyl == 4)) {
    slice(x, c(n(), 2:(n()-1), 1)) 
    } else { 
      x 
    }
  })

If you strongly prefer map:

library(dplyr)
library(purrr)

df<-list(mtcars,mtcars)



map(df, ~ 
  if (any(.x$cyl == 4)) {
    slice(.x, c(n(), 2:(n()-1), 1)) 
    } else { 
      .x 
    }
  )
Alec B
  • 159
  • 3
  • Thanks @Alec B . I understand what you say. But in my main code I need to use `ifelse`. – Laura Apr 28 '21 at 23:54
  • Why do you need to use `ifelse`? Is it because you also want to return rows where `$cyl != 4`? – Alec B Apr 28 '21 at 23:56
  • I need to in each collumn `cyl` that has value `4` the dataframe be reordenate using the `slice`function. If I have a dataframe that doesnt have the value 4 in `cyl`, nothing is done. My reproducible example should have other dataframes without values `4` in its collumns. As soon as I can I will change my reproducible example. – Laura Apr 28 '21 at 23:59
  • Ah, I think I understand your problem now. Check my edited answer. – Alec B Apr 29 '21 at 00:11