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  Mais de 600 aplicativos Bitcoin na lista negra encontrados em lojas oficiais de aplicativos, revela a investigação da RiskIQ

É 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  Versão beta dos capítulos de análise de dados: Engenharia de software baseada em evidências

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  FX HedgePool entra em operação

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