Ao trabalhar com plyr
, muitas vezes achei útil usar adply
para funções escalares que tenho que aplicar a cada linha.
por exemplo
data(iris)
library(plyr)
head(
adply(iris, 1, transform , Max.Len= max(Sepal.Length,Petal.Length))
)
Sepal.Length Sepal.Width Petal.Length Petal.Width Species Max.Len
1 5.1 3.5 1.4 0.2 setosa 5.1
2 4.9 3.0 1.4 0.2 setosa 4.9
3 4.7 3.2 1.3 0.2 setosa 4.7
4 4.6 3.1 1.5 0.2 setosa 4.6
5 5.0 3.6 1.4 0.2 setosa 5.0
6 5.4 3.9 1.7 0.4 setosa 5.4
Agora estou usando dplyr
mais, estou me perguntando se existe uma maneira organizada / natural de fazer isso? Como não é isso que eu quero:
library(dplyr)
head(
mutate(iris, Max.Len= max(Sepal.Length,Petal.Length))
)
Sepal.Length Sepal.Width Petal.Length Petal.Width Species Max.Len
1 5.1 3.5 1.4 0.2 setosa 7.9
2 4.9 3.0 1.4 0.2 setosa 7.9
3 4.7 3.2 1.3 0.2 setosa 7.9
4 4.6 3.1 1.5 0.2 setosa 7.9
5 5.0 3.6 1.4 0.2 setosa 7.9
6 5.4 3.9 1.7 0.4 setosa 7.9
mdply
no dplyr e hadley sugeriu que eles estivessem fabricando algo com basedo
. Eu acho que também funcionaria aqui.rowwise()
o que grupo por cada linha individualadply
quando você não usa um agrupamento? como sua função intimamente integrada é chamadagroup_by
NOTsplit_by
Respostas:
A partir do dplyr 0.2 (eu acho)
rowwise()
implementado, a resposta para esse problema se torna:Não
rowwise
alternativaCinco anos (!) Depois, essa resposta ainda recebe muito tráfego. Desde que foi dado,
rowwise
é cada vez mais recomendado, embora muitas pessoas pareçam achar isso intuitivo. Faça um favor a si mesmo e repasse os fluxos de trabalho orientados a Row de Jenny Bryan em R com o material arrumado para entender melhor esse tópico.A maneira mais direta que encontrei é baseada em um dos exemplos de Hadley usando
pmap
:Usando essa abordagem, você pode fornecer um número arbitrário de argumentos para a função (
.f
) dentropmap
.pmap
é uma boa abordagem conceitual porque reflete o fato de que, quando você está executando operações de linha, na verdade está trabalhando com tuplas de uma lista de vetores (as colunas em um quadro de dados).fonte
plyr
e os doisdplyr
, certamente estará usando errado, amutate
menos que forneça explicitamente o escopodplyr::mutate
.A abordagem idiomática será criar uma função adequadamente vetorizada.
R
forneça opmax
que é adequado aqui, no entanto, ele também forneceVectorize
como wrapper paramapply
permitir que você crie uma versão arbitrária vetorizada de uma função arbitrária.Observe que a implementação da vetorização em C / C ++ será mais rápida, mas não há um
magicPony
pacote que escreva a função para você.fonte
dplyr
maneira ... como seria mais simples sem o dplyr, por exemplo.with(df, Coalesce(a,b))
Talvez, esse seja um tipo de resposta - não usedplyr
para isso?magicPony
pacote. Muito ruimVocê precisa agrupar por linha:
Isto é o que o
1
fezadply
.fonte
dplyr
especialista. Espero que outra pessoa venha com algo melhor. Note que eu limpei um pouco com1:n()
.group_by(1:n())
. Se ninguém tem outras ideias na parte da manhã eu vou assinalar o seu;)n
: "Esta função é implementada especial para cada fonte de dados e só pode ser usada a partir de um resumo.", Embora pareça funcionar.Atualização 2017-08-03
Depois de escrever isso, Hadley mudou algumas coisas novamente. As funções que costumavam estar no purrr agora estão em um novo pacote misto chamado purrrlyr , descrito como:
Portanto, você precisará instalar + carregar esse pacote para fazer o código abaixo funcionar.
Postagem original
Hadley frequentemente muda de idéia sobre o que devemos usar, mas acho que devemos mudar para as funções no ronronar para obter a funcionalidade por linha. Pelo menos, eles oferecem a mesma funcionalidade e têm quase a mesma interface que
adply
do plyr .Existem duas funções relacionadas
by_row
einvoke_rows
. Meu entendimento é que você usaby_row
quando deseja fazer um loop sobre linhas e adicionar os resultados ao data.frame.invoke_rows
é usado quando você faz um loop sobre as linhas de um data.frame e passa cada coluna como argumento para uma função. Vamos usar apenas o primeiro.Exemplos
Isso nos permite ver os internos (para que possamos ver o que estamos fazendo), que é o mesmo que fazê-lo com
adply
.Por padrão,
by_row
adiciona uma coluna da lista com base na saída:dá:
se retornarmos a
data.frame
, obteremos uma lista comdata.frame
s:dá:
Como adicionamos a saída da função é controlado pelo
.collate
parâmetro Existem três opções: lista, linhas, colunas. Quando nossa saída possui comprimento 1, não importa se usamos linhas ou colunas.ambos produzem:
Se produzirmos um data.frame com 1 linha, importa apenas um pouco o que usamos:
ambos dão:
exceto que o segundo tem a coluna chamada
.row
e o primeiro não.Por fim, se nossa saída for maior que o comprimento 1 como a
vector
oudata.frame
com linhas, será importante usarmos linhas ou colunas para.collate
:produz, respectivamente:
Então, linha de fundo. Se você deseja a
adply(.margins = 1, ...)
funcionalidade, pode usarby_row
.fonte
by_row
está obsoleto, chamando-o de "use uma combinação de: tidyr :: nest (); dplyr :: mutate (); purrr :: map ()" github.com/hadley/purrrlyr/blob/…Estendendo a resposta de BrodieG,
Se a função retornar mais de uma linha, em vez de
mutate()
,do()
deverá ser usada. Em seguida, para combiná-lo novamente, userbind_all()
odplyr
pacote.Na
dplyr
versãodplyr_0.1.2
, usar1:n()
agroup_by()
cláusula não funciona para mim. Espero que o Hadley seja implementado emrowwise()
breve.Testando o desempenho,
tem os seguintes resultados:
Isso mostra que a nova
purrr
versão é a mais rápidafonte
Algo assim?
fonte
dplyr
solução geral para qualquer função escalar.wacky.function <- function(col.1, col.2){...}
e depoisiris.wacky <- wacky.function(iris$Sepal.Length, iris$Petal.Length)
.dplyr
ouplyr
ou dizdata.table
que deve tentar usar os idiomas deles para que seu código não se torne difícil de compartilhar uma mistura de estilos. Daí a questão.plyr
documentação é "plyr é um conjunto de ferramentas que resolve um conjunto comum de problemas: você precisa dividir um grande problema em pedaços gerenciáveis, operar em cada um deles e depois juntar todos os pedaços". Parece um problema muito diferente para o qual as operações elementares da coluna são a melhor ferramenta. Isso também pode explicar por que não há nenhuma "natural"plyr
/dplyr
comando para fazer isso.