1

I am a noobie at writing for loops and could use some support getting mine to work. I have a data frame that I would like filter based on values stored in a vector. I need to filter the data frame multiple times, once for each value in my vector. After each filter, I want to store the subsetted data frame and bind all the data frames together.

I found this super handy code on how to store the results of each filtered dataset and bind together - Append data frames together in a for loop

However, I can't get the code to loop over each of the values in my vector. It only loops over the first value.

Here is an example:

area <- data.frame(
  land = c("68N03E220090", "68N03E244635", "68N03E244352", "68N03E223241"),
  type = c("home", "mobile", "home", "vacant"),
  object_id = c(NA, 7, NA, 34)
)

block <- c("68N03E22", "68N03E24")

datalist = list()

for (value in block){
  df <- area %>% filter(is.na(object_id) & grepl(paste0("^", block),land))
  df$value <- value
  datalist[[value]] <- df # add it to your list
}

df_filtered <- dplyr::bind_rows(datalist)

I receive a warning:

Warning messages:
1: In grepl(paste0("^", block), land) :
  argument 'pattern' has length > 1 and only the first element will be used
2: In grepl(paste0("^", block), land) :
  argument 'pattern' has length > 1 and only the first element will be used
kwh
  • 203
  • 1
  • 8

1 Answers1

1

I think you've got a typo/error in your filter; do you get the correct output when you change "block" to "value" in your grepl? E.g.

library(tidyverse)
area <- data.frame(
  land = c("68N03E220090", "68N03E244635", "68N03E244352", "68N03E223241"),
  type = c("home", "mobile", "home", "vacant"),
  object_id = c(NA, 7, NA, 34)
)

block <- c("68N03E22", "68N03E24")

datalist = list()

for (value in block){
  df <- area %>% filter(is.na(object_id) & grepl(paste0("^", value),land))
  df$value <- value
  datalist[[value]] <- df # add it to your list
}

df_filtered <- dplyr::bind_rows(datalist)

df_filtered
#>           land type object_id    value
#> 1 68N03E220090 home        NA 68N03E22
#> 2 68N03E244352 home        NA 68N03E24

For this example, you could also avoid the for-loop by using:

df_filtered_2 <- area %>%
  filter(is.na(object_id) & grepl(pattern = paste0(block, collapse = "|"), x = land)) %>% 
  mutate(value = str_sub(land, 1, 8))

identical(df_filtered, df_filtered_2)
#> [1] TRUE
jared_mamrot
  • 22,354
  • 4
  • 21
  • 46