Ambientes (environments) em R são estruturas de dados que representam espaços onde objetos, como variáveis e funções, são associados a nomes.
Você pode pensar em um ambiente como um conjunto de nomes, sem ordem implícita.
nome ao valor Leonardo, que, por
padrão, é guardada dentro do global environment.## [1] "nome"
## [1] "Leonardo"
Nesse caso, quando “chamarmos” o símbolo nome , o R
vai procurar dentro desse environment um valor para
devolver
É possível criar novos environments com a
função new.env() ou rlang::env()
novo_ambiente = new.env() # criando o ambiente
novo_ambiente$nome <- "Nascimento" #criando objeto dentro do ambiente ou
assign(nome,"Nascimento",envir = novo_ambiente ) #criando objeto dentro do ambiente
nome## [1] "Leonardo"
## [1] "Nascimento"
rlang::env_print() para mais informações
sobre o ambiente## <environment: 0x0000017383e64008>
## Parent: <environment: global>
## Bindings:
## • nome: <chr>
## • Leonardo: <chr>
novo_ambiente.## <environment: 0x0000017383e64008>
## Parent: <environment: global>
## Bindings:
## • nome: <chr>
## • Leonardo: <chr>
## • idade: <dbl>
novo_ambiente é um environment “abaixo” do
global na hierarquia, e o R só estende a sua
busca para environments acima .a = 1 # criando um objeto no ambiente global
get("a",envir = novo_ambiente) # buscar o objeto "a" no ambiente novo_ambiente## [1] 1
parent.env()## <environment: R_GlobalEnv>
## <environment: 0x0000017383e64008>
## <environment: 0x0000017383e64008>
## Parent: <environment: global>
## Bindings:
## • nome: <chr>
## • Leonardo: <chr>
## • idade: <dbl>
## [[1]] <env: 0x0000017383e64008>
## [[2]] $ <env: global>
Essa estrutura é muito útil na hora de utilizar funções
Apenas um ambiente não possui pai: o ambiente vazio
## [[1]] <env: 0x0000017383e64008>
## [[2]] $ <env: global>
## [[3]] $ <env: package:stats>
## [[4]] $ <env: package:graphics>
## [[5]] $ <env: package:grDevices>
## [[6]] $ <env: package:utils>
## [[7]] $ <env: package:datasets>
## [[8]] $ <env: package:methods>
## [[9]] $ <env: Autoloads>
## [[10]] $ <env: package:base>
## [[11]] $ <env: empty>
## [[1]] $ <env: empty>
current_env()é o ambiente no qual o
código está sendo executado no momento.## <environment: R_GlobalEnv>
## [1] TRUE
## [1] TRUE
A atribuição regular, <-sempre cria uma variável
no ambiente atual.
A superatribuição <<-nunca cria uma variável
no ambiente atual, mas modifica uma variável existente encontrada em um
ambiente pai.
## [1] 1
Cada pacote
anexado library()ou require()torna-se um dos
pais do ambiente global.
O pai imediato do ambiente global é o último pacote que você anexou e o pai desse pacote é o penúltimo pacote que você anexou
Se você seguir todos os pais, verá a ordem em que cada pacote foi anexado. Isso é conhecido como caminho de pesquisa
Você pode ver os nomes desses ambientes
com base::search()ou os próprios ambientes
com rlang::search_envs():
## [1] ".GlobalEnv" "package:stats" "package:graphics"
## [4] "package:grDevices" "package:utils" "package:datasets"
## [7] "package:methods" "Autoloads" "package:base"
## [[1]] $ <env: global>
## [[2]] $ <env: package:stats>
## [[3]] $ <env: package:graphics>
## [[4]] $ <env: package:grDevices>
## [[5]] $ <env: package:utils>
## [[6]] $ <env: package:datasets>
## [[7]] $ <env: package:methods>
## [[8]] $ <env: Autoloads>
## [[9]] $ <env: package:base>
## <environment: R_GlobalEnv>
criar_funcao <- function() {
funcao_interna <- function() {
a=1
print("aqui")
list(ran.in = rlang::current_env(),
parent = rlang::env_parent(rlang::current_env()),
objects = ls.str(rlang::current_env()))
}
return(funcao_interna)
}
minha_funcao <- criar_funcao()
minha_funcao()## [1] "aqui"
## $ran.in
## <environment: 0x00000173804bcad8>
##
## $parent
## <environment: 0x0000017380469918>
##
## $objects
## a : num 1
## <environment: 0x0000017380469918>
## <environment: R_GlobalEnv>
Cada vez que uma função é chamada, um novo ambiente é criado para hospedar a execução. Isso é chamado de ambiente de execução e seu pai é o ambiente de função.
Eles contêm variáveis locais e referências a variáveis em escopos superiores, como o ambiente global ou ambientes de funções encapsuladoras.
Cada chamada de função tem seu próprio ambiente de execução, isolado dos ambientes de execução de outras chamadas da mesma função.
É assim que R garante que uma função não sobrescreva nada que não deveria. Quaisquer objetos criados pela função são armazenados em um ambiente de tempo de execução seguro e afastado.
show_env <- function(){
a = 1
list(ran.in = rlang::current_env(),
parent = rlang::env_parent(rlang::current_env()),
objects = ls.str(rlang::current_env()))
}
show_env()## $ran.in
## <environment: 0x00000173808384a0>
##
## $parent
## <environment: R_GlobalEnv>
##
## $objects
## a : num 1
## [1] 14
## [1] 3
<-, o novo objeto será armazenado no ambiente de
chamada.## [1] 0.09729014
## [1] -11.12911
Alguns exemplos: lapply(), apply(), e
tapply(); funcional matemático
como integrate()ou optim().
Aqui, será apresentado a família purrr::map
O funcional mais fundamental é purrr::map(). Ele
pega um vetor e uma função, chama a função uma vez para cada elemento do
vetor e retorna os resultados em uma lista.
## [1] 2 4 6 8 10 12 14 16 18 20
## [[1]]
## [1] 2
##
## [[2]]
## [1] 4
##
## [[3]]
## [1] 6
##
## [[4]]
## [1] 8
##
## [[5]]
## [1] 10
##
## [[6]]
## [1] 12
##
## [[7]]
## [1] 14
##
## [[8]]
## [1] 16
##
## [[9]]
## [1] 18
##
## [[10]]
## [1] 20
map()retorna uma lista, o que a torna a mais geral
da família de mapas.
Mas é inconveniente retornar uma lista quando uma estrutura de
dados mais simples serviria, então existem mais quatro variantes
específicas: map_lgl(), map_int(), map_dbl(),
e map_chr()
## Carregando pacotes exigidos: purrr
## mpg cyl disp hp drat wt qsec vs am gear carb
## Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4
## Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4
## Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1
## Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1
## Hornet Sportabout 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2
## Valiant 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1
## mpg cyl disp hp drat wt qsec vs
## "double" "double" "double" "double" "double" "double" "double" "double"
## am gear carb
## "double" "double" "double"
## mpg cyl disp hp drat wt qsec vs am gear carb
## TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
## mpg cyl disp hp drat wt qsec vs am gear carb
## 10 10 10 10 10 10 10 10 10 10 10
## mpg cyl disp hp drat wt qsec
## 20.090625 6.187500 230.721875 146.687500 3.596563 3.217250 17.848750
## vs am gear carb
## 0.437500 0.406250 3.687500 2.812500
x <- list(
list(5, x = 2, y = c(1), z = "A"),
list(9, x = 1, y = c(1, 6), z = "B"),
list(2, x = 10, y = c(2, 3, 5))
)
map_dbl(x, "x")## [1] 2 1 10
## [1] 5 9 2
## [1] 1 1 2
## [1] "A" "B" NA
dados_json <- '[
{"nome": "Alice", "idade": 25, "cidade": "São Paulo"},
{"nome": "Bob", "idade": 30, "cidade": "Rio de Janeiro"},
{"nome": "Charlie", "idade": 22, "cidade": "Belo Horizonte"}
]'
lista_pessoas <- rjson::fromJSON(dados_json)
# Usar map para extrair os nomes de cada pessoa
(nomes <- map_chr(lista_pessoas, "nome"))## [1] "Alice" "Bob" "Charlie"
## [1] 25 30 22
## [1] -0.448260067 0.008575166 -0.010866053 -0.008689325
## [[1]]
## [1] 0.05802109 0.08143811
##
## [[2]]
## [1] -0.87569135 0.04148435
##
## [[3]]
## [1] -0.5745417 -0.5325237
Variação: map2()
map()é vetorizado em um único
argumento, .x. Isso significa que ele varia
apenas .xdurante a chamada .fe todos os outros
argumentos são transmitidos inalterados.
Considere, por exemplo, encontrar uma média ponderada para uma lista de observações e uma lista de pesos
obs <- list(c(1,2,3),c(4,5,NA))
wd <- list(c(1,2,3),c(4,5,6))
map2_dbl(obs,wd,weighted.mean,na.rm=T)## [1] 2.333333 4.555556
pmap()obs <- list(c(1,2,3),c(4,5,NA))
wd <- list(c(1,2,3),c(4,5,6))
pmap_dbl(list(obs, wd), weighted.mean, na.rm = TRUE)## [1] 2.333333 4.555556
## [[1]]
## [1] 0.1447121
##
## [[2]]
## [1] 70.49285 93.74458
##
## [[3]]
## [1] 687.1049 402.7212 379.8194
Muitos cálculos em R podem ser feitos mais rapidamente pelo uso de computação paralela.
Geralmente, a computação paralela é a execução simultânea de diferentes partes de uma computação maior em vários processadores ou núcleos de computação
Os núcleos de um computador se referem às unidades de processamento que podem executar instruções independentes.
library(parallel)
num_nucleos <- detectCores()
nucleos = round(0.60*num_nucleos)
f <- function(i) {
return(lm(Petal.Width ~ Species, data = iris))
}
require(snowfall)
sfInit(parallel=TRUE, cpus=nucleos)
sfExportAll() # exportar os objetos para todos os núcleos
sfLibrary("nome_pacote") # exportar o pacote para todos os núcleos
system.time(sfLapply(1:100000, fun=f))
sfStop()
system.time(
for(i in 1:100000){
f(i)
}
)