Home > Blockchain >  Loop through list as input into filter() function in R
Loop through list as input into filter() function in R

Time:11-23

I'm looking to loop through all combinations of columns in a data frame and filter out rows where there are values less than zero. I've written most of the code but I'm struggling to input the values of my list into the filter function.

I started by creating my data frame 'df'. I wrote a function to get me all combinations of column names to be used as input into the filter function. I'm using if_all because I only want the rows where all columns are > 0.

Here is an example data frame

library(dplyr)
item1 <- c(-.5, 1.3, .8)
item2 <- c(.9, 2.5, 1.2)
item3 <- c(-1.2, .4, -2.1)

df <- data.frame(item1,item2,item3)

Here are all the combinations of columns I want to loop through

name_combos <- lapply(1:3, function(x) combn(c("item1","item2","item3"), x, simplify = FALSE))
name_combos <- unlist(name_combos, recursive = FALSE)

Here is where I am struggling. I'm looking for the right input so I can loop through name_combos and input each combination of column names where the '?' is.

for (i in 1:length(name_combos)) {
    results <- df %>% 
        filter(if_all(?, ~ . > 0))
    print(results)
}

Please let me know if more clarification is needed. Thank you in advance for any help.

CodePudding user response:

From Your name_combo object, you could do:

name_combos %>%
  map(~filter(df, if_all(all_of(.x), ~. > 0)))

[[1]]
  item1 item2 item3
1   1.3   2.5   0.4
2   0.8   1.2  -2.1

[[2]]
  item1 item2 item3
1  -0.5   0.9  -1.2
2   1.3   2.5   0.4
3   0.8   1.2  -2.1

[[3]]
  item1 item2 item3
1   1.3   2.5   0.4

  :
  :   

Note that combn has a function argument within it, therefore we could do: In one step, you can do the following:

map(1:3, ~combn(df, .x, \(x)filter(df, invoke(pmin, x)>0), simplify = F))

Of if you want to use if_all:

map(1:3, ~combn(names(df), .x, \(x) filter(df, if_all(all_of(x), ~.>0)), simplify = F))

You could then unlist with recursive = FALSE

For the for loop:

results <- list()
for (i in seq_along(name_combos)) {
  nms <- name_combos[[i]]
  results[[paste0(nms, collapse = "_")]] <- df %>% 
      filter(if_all(all_of(nms), ~ .> 0))
}
print(results)

$item1
  item1 item2 item3
1   1.3   2.5   0.4
2   0.8   1.2  -2.1

$item2
  item1 item2 item3
1  -0.5   0.9  -1.2
2   1.3   2.5   0.4
3   0.8   1.2  -2.1

$item3
  item1 item2 item3
1   1.3   2.5   0.4

$item1_item2
  item1 item2 item3
1   1.3   2.5   0.4
2   0.8   1.2  -2.1
  • Related