2

I want to make a simple function in R that works with data.frames/tibbles or with a data.table. So I created a new method:

pesquisarComposicao <- function(BASE, ...) {
  UseMethod("pesquisarComposicao")
}

Then I created the method for data.frames, which shows is a very simple searching function. This works very well.

pesquisarComposicao.data.frame <- function(BASE, TERMO, CAMPO = DESCRICAO) {`

  BASE |>
    filter(grepl(pattern = {{TERMO}}, x = {{CAMPO}}))
}

But the data.table method below is not working (I was following the instructions here):

pesquisarComposicao.data.table <- function(BASE, TERMO,
                                           CAMPO = "DESCRICAO DA COMPOSICAO") {

  # filter_col <- NULL
  # filter_val <- NULL

  BASE[filter_col %like% filter_val,
     env = list(
       filter_col = CAMPO,
       filter_val = I(TERMO)
     ), verbose = FALSE]
}

I have tried to insert filter_col = NULL and filter_val = NULL in order to avoid the following error:

Error in pesquisarComposicao.data.table(BASE = sinteticoSINAPI, TERMO = "PEITORIL") : object 'filter_col' not found

But then I obtained another error:

Error in grepl(pattern, vector, ignore.case = ignore.case, fixed = fixed, : invalid 'pattern' argument

I think it's weird, because when I was not yet using methods, but coded a function that should work for data.tables and simple data.frames (verified internally if the object was one of type or another), this piece of code above was working fine (and I didn't need the filter_col = NULL and filter_val = NULL). Why did it worked for a single function but it did not work as a method?

5
  • dplyr and data.table are quite different. What is TERMO, what is COMPO? It might be easier to convert from tibble or data.table to data.frame, do the operation, and coerce back. Of course, this comes with the cost of coercion, but there are tricks like quick_df Commented Apr 29 at 17:25
  • You might want something along the lines library(data.table); BASE[grepl(pattern=TERMO, x=get(CAMPO))]? Commented Apr 29 at 17:31
  • @Friede, TERMO is a character vector to be searched in the column CAMPO of the database (BASE). I have tried to convert the data.frame to data.table inside the function, but I found out that the searching with data.table became slower than with the original one, with dplyr. I think that was because of the conversion, then I decided to create methods. Commented Apr 29 at 17:41
  • I did not loaded data.table because I have added data.table as a dependency of the package, so I don't have to load it inside the function. Commented Apr 29 at 17:43
  • How can one know? Commented Apr 29 at 17:45

1 Answer 1

4

I think

library(data.table)
pesquisarComposicao <- function(BASE, ...) {
  UseMethod('pesquisarComposicao')
}
pesquisarComposicao.data.table  <- function(BASE, TERMO, CAMPO) {
  BASE[grepl(TERMO, BASE[[CAMPO]])] # non-lazy 
  
  # BASE[get(CAMPO) %like% TERMO] # get
  # BASE[grepl(TERMO, get(CAMPO))] # get
  
  # as of data.table 1.15.0 there is substitute2: 
  # BASE[grepl(pattern, x), env = I(list(pattern=TERMO, x=as.name(CAMPO)))]
  # BASE[grepl(pattern, x), env = list(pattern=I(TERMO), x=CAMPO)]
  # where `grepl`/%like% (which is like()) could have been passed as well. 
  # the docs are hard to read. 
}

does what you are after.

> pesquisarComposicao(BASE=dt, TERMO='DESCRICAO DA COMPOSICAO', CAMPO='DESCRICAO')
       ID                        DESCRICAO
   <char>                           <char>
1:      A DESCRICAO DA COMPOSICAO DE PRODU
2:      C DESCRICAO DA COMPOSICAO COMPLETA

Sample Data

as OP doesn't provide some.

dt = data.table::data.table(ID = LETTERS[1:4], DESCRICAO = c('DESCRICAO DA COMPOSICAO DE PRODU', 'INGREDIENTES NATURAIS', 'DESCRICAO DA COMPOSICAO COMPLETA', 'OUTRA COISA'))
Sign up to request clarification or add additional context in comments.

5 Comments

Strange, but this solution didn't work here. I get a message: Error in get(CAMPO) : object 'DESCRICAO' not found.
Do you want to go the modern env-way?
My purpose was to make the search faster using data.table. But since nothing seems to work, I think I'll quit!!
After several trials, what worked for me was: BASE[grepl(TERMO, BASE[[CAMPO]]), ]. Thank you, @Friede
@droubi worth to note that it will work for data.frame as well, possibly for tibbles also

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.