larry77
larry77

Reputation: 1533

Map2_df and named arguments

This must be similar to what described here

https://github.com/tidyverse/purrr/issues/179

but I am banging my head against the wall.

Consider the snippet


library(tidyverse)
library(stringr)
library(stringi)



remove_short_words <- function(x, n){

mypattern <- paste("\\w{", n, ",}", sep="")

x2 <- paste(str_extract_all(x, mypattern)[[1]], collapse=' ')


}


shopping_list <- c("apples x4", "bag of flour", "bag of sugar", "milk x2")


dd<-map2(shopping_list, 4, function(x,y) remove_short_words(x,y))


ff<-map2_df(shopping_list, 4, function(x,y) remove_short_words(x,y)) 

map2 works like a charm, but map2_df throws an error

Error: Argument 1 must have names

Any idea about how to fix this? Thanks!

#

I add what works for me. I use an auxiliary function which I plug into map




remove_short_words_aux <- function(x, n){

mypattern <- paste("\\w{", n, ",}", sep="")

x2 <- paste(str_extract_all(x, mypattern)[[1]], collapse=' ')


}



remove_short_words <- function(x,n){


res<-map(x, function(x) remove_short_words_aux(x,n)) %>%
    unlist %>%
    tibble::enframe(name = NULL)



}

> nn<-remove_short_words(shopping_list,5)
> nn
# A tibble: 4 x 1
  value   
  <chr>   
1 "apples"
2 "flour" 
3 "sugar" 
4 ""     


Upvotes: 0

Views: 1609

Answers (2)

Ronak Shah
Ronak Shah

Reputation: 388982

First I don't think you should use map2 here since n is fixed and is not changing so using map would be appropriate.

library(tidyverse)

remove_short_words <- function(x, n){
  mypattern <- paste("\\w{", n, ",}", sep="")
  paste(str_extract_all(x, mypattern)[[1]], collapse=' ')
}

shopping_list <- c("apples x4", "bag of flour", "bag of sugar", "milk x2")
map(shopping_list, remove_short_words, 4)

#[[1]]
#[1] "apples"

#[[2]]
#[1] "flour"

#[[3]]
#[1] "sugar"

#[[4]]
#[1] "milk"

Note that the output is a list of characters and if you need to combine this to one column dataframe you have two options.

  1. Use map_chr -
tibble(val = map_chr(shopping_list, remove_short_words, 4))

#   val   
#  <chr> 
#1 apples
#2 flour 
#3 sugar 
#4 milk  
  1. Or return a dataframe/tibble from the function and use map_df -
remove_short_words <- function(x, n){
  mypattern <- paste("\\w{", n, ",}", sep="")
  tibble(val = paste(str_extract_all(x, mypattern)[[1]], collapse=' '))
}

map_df(shopping_list, remove_short_words, 4)

#    val   
#  <chr> 
#1 apples
#2 flour 
#3 sugar 
#4 milk  

Moreover, since str_extract_all is vectorised you can also write this as -

remove_short_words <- function(x, n){
  mypattern <- paste0("\\w{", n, ",}")
  sapply(str_extract_all(x, mypattern), paste, collapse=' ')
}

tibble(val = remove_short_words(shopping_list, 4))

#    val   
#  <chr> 
#1 apples
#2 flour 
#3 sugar 
#4 milk  

Upvotes: 1

eastclintw00d
eastclintw00d

Reputation: 2364

I do not fully understand what you are trying to do but if your shopping_list is named this error goes away:

shopping_list2 <- shopping_list %>% 
  set_names(., shopping_list)

map2_df(shopping_list2, 4, function(x,y) remove_short_words(x,y))

Note that you don't need map2 and the additional anonymous function defintion if n is constant. Also, use map_dfr or map_dfc (or map2_dfr or map2_dfc) to specify if the data should be merged rowwise or columnwise.

map_dfr(shopping_list2, remove_short_words, n = 4)

Upvotes: 1

Related Questions