Pobre homem: O Selectificator 2000! | R-bloggers

cupom com desconto - o melhor site de cupom de desconto cupomcomdesconto.com.br


[Esteartigofoipublicadopelaprimeiravezem[Thisarticlewasfirstpublishedon Random R Ramblings, e gentilmente contribuiu para os R-blogueiros]. (Você pode relatar um problema sobre o conteúdo desta página aqui)


Deseja compartilhar seu conteúdo com R-blogueiros? clique aqui se você tiver um blog ou aqui se não tiver.

Bem-vindo à minha série de postagens de blog sobre meu pacote de manipulação de dados, {poorman}. Para aqueles de vocês que não sabem, {poorman} pretende ser uma replicação de {dplyr} mas usando apenas {base} R e, portanto, seja completamente livre de dependência. O que é legal nessa série é que, se você não curte {poorman} e prefere apenas usar {dplyr}, então está tudo bem! Destacando {poorman} funcionalidade, esta série de postagens do blog destaca simultaneamente {dplyr} funcionalidade também! No entanto, também descrevo como desenvolvi os internos de {poorman}, destacando frequentemente útil {base} R dicas e truques.

Lancei recentemente a v0.2.0 de {poorman} que você pode instalar do CRAN e, hoje, vou falar sobre meu progresso na expansão da flexibilidade do select() função. Mas não vou apenas mostrar o que isso pode fazer, vou mostrar como. Se você estiver interessado em aprender um pouco sobre a avaliação não padrão no R, não deixe de ler.

Antes da v0.2.0, {poorman} estava usando uma forma de avaliação não-padrão que converte entradas de função em cadeias de caracteres e depois as usa para descobrir quais colunas selecionar. Especificamente, {poorman} inclui a seguinte função auxiliar.

deparse_dots 

Essa é uma função não exportada, pois não é voltada para o usuário, mas você pode encontrá-la no código do GitHub aqui. Vamos analisar o que essa função faz um pouco, mas primeiro definiremos uma função temporária para mostrar por exemplo.

dummy_select 

Agora é claro que no real select() função, select() leva os dois dados (passados ​​para .data) e nomes de colunas (transmitidos para ...) como entradas e, em seguida, retorna um subconjunto do objeto de dados que contém apenas essas colunas. Em nossa função temporária, estamos apenas interessados ​​na avaliação dos nomes das colunas. Então, vamos tentar.

dummy_select(x, y)
# [1] "x" "y"

Aqui passamos dois objetos, x e y que pretendem representar os nomes de nossas colunas. Esses objetos são, de fato, símbolos que esperamos ser avaliados, mas não foram; eles são transformados em cadeias de caracteres. Isto é graças ao deparse() e substitute() combinação. deparse_dots() primeiros usos substitute() para retornar a expressão não avaliada (no nosso caso ...()) e substitui todas as variáveis ​​ligadas ao ambiente (aqui x e y) deparse_dots() depois faz um loop sobre cada uma dessas entradas e as separa. Na página de ajuda, ?deparse:

Transforme expressões não avaliadas em cadeias de caracteres.

Então agora temos nossas entradas de coluna de função como cadeias de caracteres. É um bom começo, pois agora podemos combinar essas cadeias de caracteres com os nomes das colunas dos nossos dados (match(deparse_dots(...), colnames(.data))) para obter as posições da coluna inteira de x e y. Mas e se o usuário inserir, por exemplo, um número inteiro?

dummy_select(1, 3, 5)
# [1] "1" "3" "5"

Isso agora apresenta um problema. O usuário aqui significa que deseja que a primeira, terceira e quinta colunas sejam retornadas? Ou eles significam que existem colunas dentro de suas data.frame chamado “1”, “3” e “5” – que não estão necessariamente na primeira, terceira e quinta posições – e essas são as colunas que eles gostariam? Portanto, o problema dessa abordagem é que, quando tudo é convertido em caracteres, é quase impossível saber se a entrada do usuário na função é um nome de coluna, uma posição inteira da coluna ou uma função como um auxiliar selecionado, com algum grau de certeza . A função tem que try() certas coisas, fazendo certas suposições e, claro, fazendo uma suposição faz … bem, você já ouviu o ditado.

Leia Também  Reamostragem de bootstrap com dados de produção de cerveja #TidyTuesday[0][Esteartigofoipublicadopelaprimeiravezem[Thisarticlewasfirstpublishedon Rstats em Julia Silge, e gentilmente contribuiu para os R-blogueiros]. (Você pode relatar um problema sobre o conteúdo desta página aqui)Deseja compartilhar seu conteúdo com R-blogueiros? clique aqui se você tiver um blog ou aqui se não tiver.Venho publicando screencasts demonstrando como usar a estrutura tidymodels, desde as primeiras etapas da modelagem até como ajustar modelos mais complexos. Hoje, estou usando esta semana #TidyTuesday conjunto de dados na produção de cerveja para mostrar como usar a reamostragem de autoinicialização para estimar os parâmetros do modelo. Aqui está o código que usei no vídeo, para quem prefere ler em vez de ou além do vídeo.Explore os dadosNosso objetivo de modelagem aqui é estimar quanto açúcar produtores de cerveja usam em relação a malte de acordo com o conjunto de dados #TidyTuesday. Usaremos a reamostragem de autoinicialização para fazer isso! Primeiro, vamos analisar os dados sobre os materiais de fermentação.library(tidyverse)brewing_materials_raw % count(type, wt = month_current, sort = TRUE)## # A tibble: 12 x 2## type n## ## 1 Total Used 53559516695## 2 Total Grain products 44734903124## 3 Malt and malt products 32697313882## 4 Total Non-Grain products 8824613571## 5 Sugar and syrups 6653104081## 6 Rice and rice products 5685742541## 7 Corn and corn products 5207759409## 8 Hops (dry) 1138840132## 9 Other 998968470## 10 Barley and barley products 941444745## 11 Wheat and wheat products 202642547## 12 Hops (used as extracts) 33700888Como alguns materiais diferentes de fabricação de cerveja mudaram ao longo do tempo?brewing_filtered % filter( type %in% c( "Malt and malt products", "Sugar and syrups", "Hops (dry)" ), year % mutate( date = paste0(year, "-", month, "-01"), date = lubridate::ymd(date) )brewing_filtered %>% ggplot(aes(date, month_current, color = type)) + geom_point()Existem fortes padrões anuais nesses materiais. Queremos medir quanto os produtores de cerveja com açúcar usam em relação ao malte.brewing_materials % select(date, type, month_current) %>% pivot_wider( names_from = type, values_from = month_current ) %>% janitor::clean_names()brewing_materials## # A tibble: 94 x 4## date malt_and_malt_products sugar_and_syrups hops_dry## ## 1 2008-01-01 374165152 78358212 4506546## 2 2008-02-01 355687578 80188744 1815271## 3 2008-03-01 399855819 78907213 6067167## 4 2008-04-01 388639443 81199989 6864440## 5 2008-05-01 411307544 89946309 7470130## 6 2008-06-01 415161326 81012422 7361941## 7 2008-07-01 405393784 76728131 1759452## 8 2008-08-01 389391266 83928121 5992025## 9 2008-09-01 362587470 71982604 3788942## 10 2008-10-01 353803777 42828943 3788949## # … with 84 more rowsbrewing_materials %>% ggplot(aes(malt_and_malt_products, sugar_and_syrups)) + geom_smooth(method = "lm") + geom_point()Há muita variação nesse relacionamento, mas os reprodutores de cerveja usam mais açúcar quando usam mais malte. Qual é a relação?library(tidymodels)beer_fit |t|) ## malt_and_malt_products 0.205804 0.003446 59.72

É aqui que as atualizações para o poorman::select() função. Como usuário, quero poder passar números inteiros, numéricos, seqüências de caracteres, símbolos e até funções a serem interpretadas pelo select() funcione corretamente e retorne as colunas que desejo. É aqui que entra a próxima linha de código – que é absolutamente brilhante -.

eval(substitute(alist(...)))

Vamos quebrar essa função e ver o que ela faz. Trabalharemos com uma função e a construiremos pouco a pouco.

dummy_select 

Ok, não é tão emocionante, certo? E se envolvermos isso em substituição?

dummy_select 

Agora podemos ver que conseguimos transmitir nossas informações, mas elas parecem estar envolvidas em uma chamada não avaliada para alist(), então vamos tentar avaliar.

dummy_select 

Perfeito! Agora, temos nossas entradas de função não avaliadas armazenadas em uma lista. Mas o que há de tão bom nisso? Bem, vamos dar uma olhada na estrutura dessa saída.

cupom com desconto - o melhor site de cupom de desconto cupomcomdesconto.com.br
str(dummy_select(x, y))
# List of 2
#  $ : symbol x
#  $ : symbol y

Portanto, podemos ver que nossas entradas foram armazenadas como sua classe apropriada; símbolos! De fato, isso ocorre independentemente do que usamos como nossos insumos.

str(dummy_select(1L, 2, "x", y, starts_with("R")))
# List of 5
#  $ : int 1
#  $ : num 2
#  $ : chr "x"
#  $ : symbol y
#  $ : language starts_with("R")

Isto é fantástico. O que isso significa é que agora podemos definir funcionalidades que podem lidar com cada um dos tipos separados que normalmente esperamos serem usados ​​em uma chamada para select(). Toda essa mágica é devida à alist() função, vamos dar uma olhada na documentação.

alist lida com seus argumentos como se eles descrevessem argumentos de função. Portanto, os valores não são avaliados e argumentos marcados sem valor são permitidos, enquanto list simplesmente os ignora.

Então, se tivéssemos usado o list() função, teria tentado avaliar nossas entradas para o dummy_select() função enquanto alist() não – ele os armazena como objetos não avaliados.

Leia Também  Charada: Você pode dizer quando a neve começou?

Agora, isso começa a ficar realmente interessante quando começamos a dar uma olhada no language entradas. Ao usar dplyr::select(), o usuário pode selecionar colunas de várias maneiras. Vamos dar uma olhada em alguns deles e como é a estrutura deles.

str(dummy_select(!w, x:y, -z))
# List of 3
#  $ : language !w
#  $ : language x:y
#  $ : language -z

Portanto, selecionar colunas através do uso de um ponto de exclamação (negação), dois pontos ou sinal de menos na verdade nos dá uma language objeto. Tá, e daí? O que há de tão especial nisso? Bem, o que torna isso tão útil para nós é como podemos interagir com os objetos. Na verdade, podemos acessar partes do language objeto, da mesma maneira que fazemos com um list(). Vamos dar uma olhada.

obj 

Portanto, os operadores são realmente funções. De fato, em R, tudo é um objeto e interagimos com esses objetos usando funções, então isso faz sentido. Vamos analisar um pouco mais esse objeto.

obj[[1]][[1]]
# `:`
obj[[1]][[2]]
# x
obj[[1]][[3]]
# y

Então, nossa entrada de função, x:y, podem ser divididos em componentes individuais. Sabemos que os componentes são compostos da função do cólon, bem como x e y, mas qual é a estrutura desses dois componentes finais?

str(obj[[1]][[2]])
#  symbol x
str(obj[[1]][[3]])
#  symbol y

Eles são símbolos! Portanto, agora podemos lidar com isso da mesma maneira que fizemos com as entradas de símbolo na primeira instância, porque lembre-se, basta passar x ou y para nosso dummy_select() A função retornou um símbolo.

str(dummy_select(x, y))
# List of 2
#  $ : symbol x
#  $ : symbol y

Então aí está! É assim que você, como usuário, agora pode executar select() liga com {poorman} como isso:

library(poorman, warn.conflicts = FALSE)
mtcars %>%
  select(drat, mpg:hp, starts_with("g"), everything()) %>%
  head()
#                   drat  mpg cyl disp  hp gear    wt  qsec vs am carb
# Mazda RX4         3.90 21.0   6  160 110    4 2.620 16.46  0  1    4
# Mazda RX4 Wag     3.90 21.0   6  160 110    4 2.875 17.02  0  1    4
# Datsun 710        3.85 22.8   4  108  93    4 2.320 18.61  1  1    1
# Hornet 4 Drive    3.08 21.4   6  258 110    3 3.215 19.44  1  0    1
# Hornet Sportabout 3.15 18.7   8  360 175    3 3.440 17.02  0  0    2
# Valiant           2.76 18.1   6  225 105    3 3.460 20.22  1  0    1
Leia Também  T ^ 4 # 7 e R ^ 4 # 5: Binários R e CRAN para Ubuntu

Esta publicação examinou duas abordagens de avaliação não padronizadas separadas – usando apenas {base} – implantado dentro do {poorman} pacote. Vimos como quebrar language objetos para coletar informações importantes sobre eles. Também vimos como determinar os tipos de objeto de entradas de função e por que isso é importante a considerar. Em particular, isso mostrou como eu era capaz de transformar o select() função para a função seletor de ômega… da desgraça.

Como esta postagem no blog é bastante longa, não entrei em mais detalhes sobre os internos de {poorman} no entanto, se você estiver interessado em examinar mais de perto como eu manejo os diferentes tipos de entrada, poderá ver o código na {poorman} Página do GitHub. {poorman} ainda é um trabalho em andamento, mas como você pode ver, ele já possui muitas funcionalidades que você conhece e ama {dplyr} portanto, se você estiver trabalhando em um novo projeto e não quiser lidar com o gerenciamento de dependências, especialmente se estiver compartilhando trabalho com colegas, por que não dar {poorman} uma tentativa?

Se você deseja mostrar seu apoio a {poorman}, considere atribuir ao pacote uma estrela no Github, pois ele me dá o impulso de dopamina necessário para continuar o desenvolvimento.



Se você chegou até aqui, por que não inscreva-se para atualizações do site? Escolha o seu sabor: e-mail, twitter, RSS ou facebook …



cupom com desconto - o melhor site de cupom de desconto cupomcomdesconto.com.br