Eu quero usar dplyr::mutate()
para criar várias novas colunas em um quadro de dados. Os nomes das colunas e seu conteúdo devem ser gerados dinamicamente.
Dados de exemplo da íris:
library(dplyr)
iris <- tbl_df(iris)
Eu criei uma função para alterar minhas novas colunas da Petal.Width
variável:
multipetal <- function(df, n) {
varname <- paste("petal", n , sep=".")
df <- mutate(df, varname = Petal.Width * n) ## problem arises here
df
}
Agora eu crio um loop para construir minhas colunas:
for(i in 2:5) {
iris <- multipetal(df=iris, n=i)
}
No entanto, como mutate acha que varname é um nome literal de variável, o loop cria apenas uma nova variável (chamada varname) em vez de quatro (chamada petal.2 - petal.5).
Como posso mutate()
usar meu nome dinâmico como nome de variável?
dplyr
tem uma vinheta todo na avaliação não-padrãomutate_
, e realmente não é óbvio pelas outras funções como usá-la.Respostas:
Como você está construindo dinamicamente um nome de variável como um valor de caractere, faz mais sentido fazer a atribuição usando a indexação data.frame padrão que permite valores de caracteres para nomes de colunas. Por exemplo:
A
mutate
função facilita muito o nome de novas colunas por meio de parâmetros nomeados. Mas isso pressupõe que você saiba o nome ao digitar o comando. Se você deseja especificar dinamicamente o nome da coluna, também precisa criar o argumento nomeado.versão dplyr> = 0.7
A versão mais recente do
dplyr
(0.7) faz isso usando:=
para atribuir dinamicamente nomes de parâmetros. Você pode escrever sua função como:Para mais informações, consulte o formulário disponível na documentação
vignette("programming", "dplyr")
.dplyr (> = 0,3 e <0,7)
A versão ligeiramente anterior de
dplyr
(> = 0.3 <0.7) incentivou o uso de alternativas de "avaliação padrão" para muitas das funções. Consulte a vinheta de avaliação não padrão para obter mais informações (vignette("nse")
).Então aqui, a resposta é usar
mutate_()
e nãomutate()
fazer:dplyr <0,3
Observe que isso também é possível nas versões mais antigas
dplyr
que existiam quando a pergunta foi feita originalmente. Requer o uso cuidadosoquote
esetName
:fonte
do.call()
provavelmente não faz o que você pensa: rpubs.com/hadley/do-call2 . Veja também a vinheta nse na versão dev do dplyr.do.call
acima para usardo.call("mutate")
e citardf
na lista. Era isso que você estava sugerindo? E quando alazyeval
versão dodplyr
é a versão lançada, entãomutate_(df, .dots= setNames(list(~Petal.Width * n), varname))
seria uma solução melhor?mutate(df, !!newVar := (!!var1 + !!var2) / 2)
, não funciona :(Na nova versão de
dplyr
(0.6.0
aguardando em abril de 2017), também podemos fazer uma atribuição (:=
) e passar variáveis como nomes de colunas, sem citar (!!
) para não avaliá-laVerificando a saída com base no @ MrFlick
multipetal
aplicado em 'iris1'fonte
Após muitas tentativas e erros, achei o padrão
UQ(rlang::sym("some string here")))
realmente útil para trabalhar com strings e verbos dplyr. Parece funcionar em muitas situações surpreendentes.Aqui está um exemplo com
mutate
. Queremos criar uma função que adicione duas colunas, onde você passa a função pelos nomes de colunas como strings. Podemos usar esse padrão, juntamente com o operador de atribuição:=
, para fazer isso.O padrão também funciona com outras
dplyr
funções. Aqui estáfilter
:Ou
arrange
:Para
select
, você não precisa usar o padrão. Em vez disso, você pode usar!!
:fonte
myCol
para uma URL (por exemplo) e copio a coluna antigamyColInitialValue
no final do quadro de dadosdf
com um novo nome. Maswhich(colnames(df)=='myCol')
envie de volta o número da colunamyColInitialValue
. Ainda não escrevi um problema porque não encontrei um reprex. Meu objetivo é oescape
parâmetro deDT::datatable()
. Eu usoescape=FALSE
esperando isso. Com constantes, ele também não funciona, mas o pacote DT também parece ter a coluna # ruim. :)escape
umDT::datatable
varname = sym("Petal.Width"); ggplot(iris, aes(x=!!varname)) + geom_histogram()
Aqui está outra versão, e é sem dúvida um pouco mais simples.
fonte
Com
rlang 0.4.0
, temos operadores curly-curly ({{}}
), o que facilita muito isso.Também podemos passar nomes de variáveis entre aspas / não citadas para serem atribuídos como nomes de colunas.
Funciona da mesma maneira com
fonte
Também estou adicionando uma resposta que aumenta um pouco isso, porque cheguei a esta entrada ao procurar uma resposta, e isso tinha quase o que eu precisava, mas precisava de um pouco mais, o que recebi através da resposta do @MrFlik e do R vinhetas preguiçosas.
Eu queria criar uma função que pudesse levar um quadro de dados e um vetor de nomes de colunas (como seqüências de caracteres) que desejo que sejam convertidos de uma sequência para um objeto Date. Não consegui descobrir como
as.Date()
usar um argumento que é uma string e convertê-lo em uma coluna, então fiz como mostrado abaixo.Abaixo está como eu fiz isso via SE mutate (
mutate_()
) e o.dots
argumento. Críticas que melhoram isso são bem-vindas.fonte
Embora eu goste de usar o dplyr para uso interativo, acho extraordinariamente complicado fazer isso usando o dplyr, porque você precisa passar por etapas para usar as soluções alternativas lazyeval :: interp (), setNames, etc.
Aqui está uma versão mais simples usando a base R, na qual parece mais intuitivo, pelo menos para mim, colocar o loop dentro da função e que estende a solução do @ MrFlicks.
fonte
dplyr
muito em configurações não interativas, usá-lo com entrada variável dentro de uma função usa sintaxe muito desajeitada.Você pode aproveitar o pacote
friendlyeval
que apresenta uma API de avaliação organizada e simplificada paradplyr
usuários mais novos / casuais .Você está criando cadeias que deseja
mutate
tratar como nomes de colunas. Então, usandofriendlyeval
você pode escrever:Que sob o capô chama
rlang
funções que a verificaçãovarname
é legal como nome da coluna.friendlyeval
O código pode ser convertido em código de avaliação simples e arrumado a qualquer momento com um complemento do RStudio.fonte
Outra alternativa: use
{}
aspas para criar facilmente nomes dinâmicos. Isso é semelhante a outras soluções, mas não exatamente o mesmo, e acho mais fácil.Eu acho que isso vem,
dplyr 1.0.0
mas não tenho certeza (eu também tenho,rlang 4.7.0
se importa).fonte