Funcionamento (implementação) da função apply (lapply) em loops

Boa noite, gostaria de entender o funcionamento da função apply, mais precisamente lapply, para loops. Já conheço a descrição de seu funcionamento: ‘lapply’ returns a list of the same length as ‘X’, each element of which is the result of applying ‘FUN’ to the corresponding element of ‘X’. Mas o que eu gostaria de saber é como ele funciona em sua essência. Por exemplo, utilizar um lapply ao invés de um loop "for" é mais rápido. Eu gostaria de saber o porque, ou seja, como o lapply é implementado. Não sei se fui claro, mas gostaria de encontrar a implementação da função lapply, o que não encontrei no diretório do pacote "base". Se alguém puder ajudar. Também peço desculpas por não ter dado grandes contribuições para a lista, mas creio ter mais experiência em programação (lógica) de fato, do que no ambiente R. Obrigado. -- Carlos Roberto Beleti Junior Mestrado em Ciência da Computação Departamento de Informática Universidade Estadual de Maringá

Júnior, para ver o código fonte da função lapply, ou se quiser aprofundar-se na apply entre no CRAN baixe o código fonte (extensão .tar.gz) e vá no diretório: /R-2.13.0/src/library/bae/R/. Lá estarão todos arquivos .R das funções do base! Vale lembrar que algumas delas tem partes ou o todo implementadas em outras linguagens, segue o exemplo do lapply: lapply <- function (X, FUN, ...) { FUN <- match.fun(FUN) ## internal code handles all vector types, including expressions ## However, it would be OK to have attributes which is.vector ## disallows. if(!is.vector(X) || is.object(X)) X <- as.list(X) .Internal(lapply(X, FUN)) } rapply <- function(object, f, classes = "ANY", deflt = NULL, how = c("unlist", "replace", "list"), ...) { if(typeof(object) != "list") stop("'object' must be a list") how <- match.arg(how) res <- .Internal(rapply(object, f, classes, deflt, how)) if(how == "unlist") unlist(res, recursive = TRUE) else res } abraço, FH 2011/6/13 Junior Beleti <beleti.junior@gmail.com>
Boa noite,
gostaria de entender o funcionamento da função apply, mais precisamente lapply, para loops.
Já conheço a descrição de seu funcionamento:
‘lapply’ returns a list of the same length as ‘X’, each element of which is the result of applying ‘FUN’ to the corresponding element of ‘X’.
Mas o que eu gostaria de saber é como ele funciona em sua essência. Por exemplo, utilizar um lapply ao invés de um loop "for" é mais rápido. Eu gostaria de saber o porque, ou seja, como o lapply é implementado.
Não sei se fui claro, mas gostaria de encontrar a implementação da função lapply, o que não encontrei no diretório do pacote "base".
Se alguém puder ajudar.
Também peço desculpas por não ter dado grandes contribuições para a lista, mas creio ter mais experiência em programação (lógica) de fato, do que no ambiente R.
Obrigado.
-- Carlos Roberto Beleti Junior Mestrado em Ciência da Computação Departamento de Informática Universidade Estadual de Maringá
_______________________________________________ R-br mailing list R-br@listas.c3sl.ufpr.br https://listas.inf.ufpr.br/cgi-bin/mailman/listinfo/r-br Leia o guia de postagem (http://www.leg.ufpr.br/r-br-guia) e forneça código mínimo reproduzível.

Faça o download do tar.gz do R e veja a função. http://www.cran.r-project.org/bin/linux/ubuntu/lucid/r-base_2.13.0.orig.tar.... Fábio Mathias Corrêa Universidade Estadual de Santa Cruz Departamento de Ciências Exatas e da Terra - DCET Campus Soane Nazaré de Andrade, km 16 Rodovia Ilhéus-Itabuna CEP 45662-900. Ilhéus-Bahia Tel.: 73-3680-5076 ________________________________ De: Junior Beleti <beleti.junior@gmail.com> Para: r-br@listas.c3sl.ufpr.br Enviadas: Segunda-feira, 13 de Junho de 2011 23:12 Assunto: [R-br] Funcionamento (implementação) da função apply (lapply) em loops Boa noite, gostaria de entender o funcionamento da função apply, mais precisamente lapply, para loops. Já conheço a descrição de seu funcionamento: ‘lapply’ returns a list of the same length as ‘X’, each element of which is the result of applying ‘FUN’ to the corresponding element of ‘X’. Mas o que eu gostaria de saber é como ele funciona em sua essência. Por exemplo, utilizar um lapply ao invés de um loop "for" é mais rápido. Eu gostaria de saber o porque, ou seja, como o lapply é implementado. Não sei se fui claro, mas gostaria de encontrar a implementação da função lapply, o que não encontrei no diretório do pacote "base". Se alguém puder ajudar. Também peço desculpas por não ter dado grandes contribuições para a lista, mas creio ter mais experiência em programação (lógica) de fato, do que no ambiente R. Obrigado. -- Carlos Roberto Beleti Junior Mestrado em Ciência da Computação Departamento de Informática Universidade Estadual de Maringá _______________________________________________ R-br mailing list R-br@listas.c3sl.ufpr.br https://listas.inf.ufpr.br/cgi-bin/mailman/listinfo/r-br Leia o guia de postagem (http://www.leg.ufpr.br/r-br-guia) e forneça código mínimo reproduzível.

https://svn.r-project.org/R/branches/R-2-13-branch/src/main/apply.c 2011/6/14 Fabio Mathias Corrêa <fabio.ufla@yahoo.com.br>:
Faça o download do tar.gz do R e veja a função. http://www.cran.r-project.org/bin/linux/ubuntu/lucid/r-base_2.13.0.orig.tar....
Fábio Mathias Corrêa
Universidade Estadual de Santa Cruz Departamento de Ciências Exatas e da Terra - DCET
Campus Soane Nazaré de Andrade, km 16 Rodovia Ilhéus-Itabuna CEP 45662-900. Ilhéus-Bahia
Tel.: 73-3680-5076 ________________________________ De: Junior Beleti <beleti.junior@gmail.com> Para: r-br@listas.c3sl.ufpr.br Enviadas: Segunda-feira, 13 de Junho de 2011 23:12 Assunto: [R-br] Funcionamento (implementação) da função apply (lapply) em loops
Boa noite,
gostaria de entender o funcionamento da função apply, mais precisamente lapply, para loops.
Já conheço a descrição de seu funcionamento:
‘lapply’ returns a list of the same length as ‘X’, each element of which is the result of applying ‘FUN’ to the corresponding element of ‘X’.
Mas o que eu gostaria de saber é como ele funciona em sua essência. Por exemplo, utilizar um lapply ao invés de um loop "for" é mais rápido. Eu gostaria de saber o porque, ou seja, como o lapply é implementado.
Não sei se fui claro, mas gostaria de encontrar a implementação da função lapply, o que não encontrei no diretório do pacote "base".
Se alguém puder ajudar.
Também peço desculpas por não ter dado grandes contribuições para a lista, mas creio ter mais experiência em programação (lógica) de fato, do que no ambiente R.
Obrigado.
-- Carlos Roberto Beleti Junior Mestrado em Ciência da Computação Departamento de Informática Universidade Estadual de Maringá
_______________________________________________ R-br mailing list R-br@listas.c3sl.ufpr.br https://listas.inf.ufpr.br/cgi-bin/mailman/listinfo/r-br Leia o guia de postagem (http://www.leg.ufpr.br/r-br-guia) e forneça código mínimo reproduzível.
_______________________________________________ R-br mailing list R-br@listas.c3sl.ufpr.br https://listas.inf.ufpr.br/cgi-bin/mailman/listinfo/r-br Leia o guia de postagem (http://www.leg.ufpr.br/r-br-guia) e forneça código mínimo reproduzível.

Atualmente, a ideia de *apply() ser mais rapido que for() nao eh exatamente verdadeira. A diferenca essencial (as far as users care) entre ambas eh que a familia *apply cria um objeto de resposta para cada elemento de entrada, ao passo que usuarios do for() fazem alocacao da resposta a objetos pre-existentes (o que dispara uma copia e, consequentemente, faz com que a execucao seja mais lenta). Veja o exemplo abaixo (mude as dimensoes caso vc nao tenha RAM suficiente): nc <- 1e6 nr <- 200 ## com sapply set.seed(1) t0 <- system.time(res0 <- sapply(1:nr, function(x) rnorm(nc))) ## com for() usando o q a maioria de usuarios faz... set.seed(1) t1 <- system.time({res1 <- NULL; for (i in 1:nr) res1 <- cbind(res1, rnorm(nc))}) all.equal(res0, res1) ## deve ser TRUE rm(res0) ## com for() mais eficiente set.seed(1) t2 <- system.time({res2 <- matrix(NA, nc=nr, nr=nc); for (i in 1:nr) res2[,i] <- rnorm(nc)}) all.equal(res1, res2) ## deve ser TRUE rm(res1); gc() ## com lapply() set.seed(1) t3 <- system.time(res3 <- do.call(cbind, lapply(1:nr, function(x) rnorm(nc)))) all.equal(res2, res3) ## deve ser TRUE rm(res2, res3); gc() ## visualizando tempos message(sprintf('sapply...........: %2.4f', t0[3])) message(sprintf('for() usual......: %2.4f', t1[3])) message(sprintf('for() pre-aloc..: %2.4f', t2[3])) message(sprintf('do.call+lapply: %2.4f', t3[3])) Os resultados que obtive na minha maquina sao: sapply...........: 20.5400 for() usual......: 207.3900 for() pre-aloc..: 21.7730 do.call+lapply: 18.3960 Take-home messages: 1) for() mais lento e' fato qdo a programacao e' ineficiente; 2) lapply() e' sempre mais eficiente que sapply() Take-home exercise: repita o for() com pre-alocacao usando listas, combinando o resultado com do.call()... Isso e' tao rapido quanto o do.call+lapply (na verdade, na minha execucao, ele eh ainda ligeiramente mais rapido... levando 18.385s)... b 2011/6/14 Junior Beleti <beleti.junior@gmail.com>:
Boa noite,
gostaria de entender o funcionamento da função apply, mais precisamente lapply, para loops.
Já conheço a descrição de seu funcionamento:
‘lapply’ returns a list of the same length as ‘X’, each element of which is the result of applying ‘FUN’ to the corresponding element of ‘X’.
Mas o que eu gostaria de saber é como ele funciona em sua essência. Por exemplo, utilizar um lapply ao invés de um loop "for" é mais rápido. Eu gostaria de saber o porque, ou seja, como o lapply é implementado.
Não sei se fui claro, mas gostaria de encontrar a implementação da função lapply, o que não encontrei no diretório do pacote "base".
Se alguém puder ajudar.
Também peço desculpas por não ter dado grandes contribuições para a lista, mas creio ter mais experiência em programação (lógica) de fato, do que no ambiente R.
Obrigado.
-- Carlos Roberto Beleti Junior Mestrado em Ciência da Computação Departamento de Informática Universidade Estadual de Maringá
_______________________________________________ R-br mailing list R-br@listas.c3sl.ufpr.br https://listas.inf.ufpr.br/cgi-bin/mailman/listinfo/r-br Leia o guia de postagem (http://www.leg.ufpr.br/r-br-guia) e forneça código mínimo reproduzível.
-- Successful people ask better questions, and as a result, they get better answers. (Tony Robbins)

Que bonita demostração Benilton, vou fazer a liçãod e casa aqui, valeu! att, FH 2011/6/14 Benilton Carvalho <beniltoncarvalho@gmail.com>
Atualmente, a ideia de *apply() ser mais rapido que for() nao eh exatamente verdadeira.
A diferenca essencial (as far as users care) entre ambas eh que a familia *apply cria um objeto de resposta para cada elemento de entrada, ao passo que usuarios do for() fazem alocacao da resposta a objetos pre-existentes (o que dispara uma copia e, consequentemente, faz com que a execucao seja mais lenta).
Veja o exemplo abaixo (mude as dimensoes caso vc nao tenha RAM suficiente):
nc <- 1e6 nr <- 200
## com sapply set.seed(1) t0 <- system.time(res0 <- sapply(1:nr, function(x) rnorm(nc)))
## com for() usando o q a maioria de usuarios faz... set.seed(1) t1 <- system.time({res1 <- NULL; for (i in 1:nr) res1 <- cbind(res1, rnorm(nc))}) all.equal(res0, res1) ## deve ser TRUE rm(res0)
## com for() mais eficiente set.seed(1) t2 <- system.time({res2 <- matrix(NA, nc=nr, nr=nc); for (i in 1:nr) res2[,i] <- rnorm(nc)}) all.equal(res1, res2) ## deve ser TRUE rm(res1); gc()
## com lapply() set.seed(1) t3 <- system.time(res3 <- do.call(cbind, lapply(1:nr, function(x) rnorm(nc)))) all.equal(res2, res3) ## deve ser TRUE rm(res2, res3); gc()
## visualizando tempos message(sprintf('sapply...........: %2.4f', t0[3])) message(sprintf('for() usual......: %2.4f', t1[3])) message(sprintf('for() pre-aloc..: %2.4f', t2[3])) message(sprintf('do.call+lapply: %2.4f', t3[3]))
Os resultados que obtive na minha maquina sao:
sapply...........: 20.5400 for() usual......: 207.3900 for() pre-aloc..: 21.7730 do.call+lapply: 18.3960
Take-home messages:
1) for() mais lento e' fato qdo a programacao e' ineficiente; 2) lapply() e' sempre mais eficiente que sapply()
Take-home exercise: repita o for() com pre-alocacao usando listas, combinando o resultado com do.call()... Isso e' tao rapido quanto o do.call+lapply (na verdade, na minha execucao, ele eh ainda ligeiramente mais rapido... levando 18.385s)...
b
2011/6/14 Junior Beleti <beleti.junior@gmail.com>:
Boa noite,
gostaria de entender o funcionamento da função apply, mais precisamente lapply, para loops.
Já conheço a descrição de seu funcionamento:
‘lapply’ returns a list of the same length as ‘X’, each element of which is the result of applying ‘FUN’ to the corresponding element of ‘X’.
Mas o que eu gostaria de saber é como ele funciona em sua essência. Por exemplo, utilizar um lapply ao invés de um loop "for" é mais rápido. Eu gostaria de saber o porque, ou seja, como o lapply é implementado.
Não sei se fui claro, mas gostaria de encontrar a implementação da função lapply, o que não encontrei no diretório do pacote "base".
Se alguém puder ajudar.
Também peço desculpas por não ter dado grandes contribuições para a lista, mas creio ter mais experiência em programação (lógica) de fato, do que no ambiente R.
Obrigado.
-- Carlos Roberto Beleti Junior Mestrado em Ciência da Computação Departamento de Informática Universidade Estadual de Maringá
_______________________________________________ R-br mailing list R-br@listas.c3sl.ufpr.br https://listas.inf.ufpr.br/cgi-bin/mailman/listinfo/r-br Leia o guia de postagem (http://www.leg.ufpr.br/r-br-guia) e forneça código mínimo reproduzível.
-- Successful people ask better questions, and as a result, they get better answers. (Tony Robbins) _______________________________________________ R-br mailing list R-br@listas.c3sl.ufpr.br https://listas.inf.ufpr.br/cgi-bin/mailman/listinfo/r-br Leia o guia de postagem (http://www.leg.ufpr.br/r-br-guia) e forneça código mínimo reproduzível.
participantes (5)
-
Benilton Carvalho
-
Fabio Mathias Corrêa
-
Fernando Henrique Toledo
-
Gustavo Henrique de Carvalho
-
Junior Beleti