Sempre que eu quero fazer algo "mapear" py em R, geralmente tento usar uma função na apply
família.
No entanto, nunca entendi bem as diferenças entre eles - como { sapply
, lapply
etc.} aplica a função à entrada / entrada agrupada, como será a saída ou até mesmo como pode ser a entrada - por isso, muitas vezes basta passar por todos eles até conseguir o que quero.
Alguém pode explicar como usar qual quando?
Meu entendimento atual (provavelmente incorreto / incompleto) é ...
sapply(vec, f)
: input é um vetor. output é um vetor / matriz, onde elementoi
éf(vec[i])
, fornecendo uma matriz sef
tiver uma saída com vários elementoslapply(vec, f)
: o mesmo quesapply
, mas a saída é uma lista?apply(matrix, 1/2, f)
: input é uma matriz. output é um vetor, em que o elementoi
é f (linha / coli da matriz)tapply(vector, grouping, f)
: output é uma matriz / matriz, em que um elemento na matriz / matriz é o valor def
um agrupamentog
do vetor eg
é empurrado para os nomes de linha / colunaby(dataframe, grouping, f)
: deixeg
ser um agrupamento. aplicarf
a cada coluna do grupo / quadro de dados. imprima o agrupamento e o valor def
em cada coluna.aggregate(matrix, grouping, f)
: semelhante aby
, mas em vez de imprimir bastante a saída, o agregado agrupa tudo em um quadro de dados.
Pergunta Side: Eu ainda tenho plyr ou remodelar não aprendeu - se plyr
ou reshape
substituir todos estes inteiramente?
*apply()
eby
. O plyr (pelo menos para mim) parece muito mais consistente, porque eu sempre sei exatamente qual formato de dados ele espera e exatamente o que ele vai cuspir. Isso me poupa muito aborrecimento.doBy
e os recursos de seleção e aplicação dedata.table
.sapply
é apenaslapply
com a adição desimplify2array
na saída.apply
coagir ao vetor atômico, mas a saída pode ser vetorial ou lista.by
divide os quadros de dados em sub-quadros de dados, mas não é usadof
nas colunas separadamente. Somente se houver um método para a classe 'data.frame' forf
aplicado por colunaby
.aggregate
é genérico, portanto existem métodos diferentes para diferentes classes do primeiro argumento.Respostas:
R possui muitas funções * apply que são descritas habilmente nos arquivos de ajuda (por exemplo
?apply
). Porém, existem muitos deles, para que os usuários iniciais possam ter dificuldade em decidir qual deles é apropriado para a situação ou até mesmo se lembrar de todos. Eles podem ter um senso geral de que "eu deveria estar usando uma função * apply aqui", mas pode ser difícil mantê-los corretos no início.Apesar do fato (observado em outras respostas) de que grande parte da funcionalidade da família * apply é coberta pelo
plyr
pacote extremamente popular , as funções básicas permanecem úteis e vale a pena conhecer.Esta resposta pretende atuar como uma espécie de sinalização para novos useRs para ajudar a direcioná-los para a função correta * apply para seu problema específico. Observe que isso não se destina a regurgitar ou substituir a documentação do R! A esperança é que essa resposta o ajude a decidir qual função * aplicada se adequa à sua situação e, então, cabe a você pesquisar mais. Com uma exceção, as diferenças de desempenho não serão abordadas.
aplicar - Quando você deseja aplicar uma função às linhas ou colunas de uma matriz (e análogos de dimensões superiores); geralmente não é aconselhável para quadros de dados, pois ele coagirá a uma matriz primeiro.
Se você quiser meio de linha / coluna ou somas para uma matriz 2D, certifique-se de investigar o altamente otimizado,-relâmpago
colMeans
,rowMeans
,colSums
,rowSums
.lapply - Quando você deseja aplicar uma função a cada elemento de uma lista e obter uma lista de volta.
Este é o cavalo de batalha de muitas das outras funções * apply. Descasque o código e você encontrará frequentemente
lapply
embaixo.sapply - Quando você deseja aplicar uma função a cada elemento de uma lista, por sua vez, mas deseja um vetor de volta, em vez de uma lista.
Se você estiver digitando
unlist(lapply(...))
, pare e consideresapply
.Em usos mais avançados,
sapply
ele tentará coagir o resultado a uma matriz multidimensional, se apropriado. Por exemplo, se nossa função retornar vetores do mesmo comprimento,sapply
os usará como colunas de uma matriz:Se nossa função retornar uma matriz bidimensional,
sapply
fará essencialmente a mesma coisa, tratando cada matriz retornada como um único vetor longo:A menos que seja especificado
simplify = "array"
, nesse caso, ele usará as matrizes individuais para criar uma matriz multidimensional:É claro que cada um desses comportamentos depende de nossa função retornar vetores ou matrizes do mesmo comprimento ou dimensão.
vapply - Quando você deseja usar, mas talvez precise extrair um pouco mais de velocidade do seu código.
sapply
Para
vapply
, basicamente, você fornece a R um exemplo de que tipo de coisa sua função retornará, o que pode economizar tempo coagindo os valores retornados a se ajustarem a um único vetor atômico.mapply - Para quando você possui várias estruturas de dados (por exemplo, vetores, listas) e deseja aplicar uma função aos 1º elementos de cada um e depois aos 2º elementos de cada um, etc., coagindo o resultado a um vetor / matriz como em
sapply
.Isso é multivariado no sentido de que sua função deve aceitar vários argumentos.
Mapa - Um wrapper para
mapply
withSIMPLIFY = FALSE
, portanto, é garantido que você retorne uma lista.rapply - para quando você deseja aplicar uma função a cada elemento de uma estrutura de lista aninhada , recursivamente.
Para ter uma idéia de como
rapply
é incomum , eu esqueci disso ao postar esta resposta pela primeira vez! Obviamente, tenho certeza que muitas pessoas usam, mas YMMV.rapply
é melhor ilustrado com uma função definida pelo usuário a ser aplicada:tapply - para quando você deseja aplicar uma função a subconjuntos de um vetor e os subconjuntos são definidos por algum outro vetor, geralmente um fator.
As ovelhas negras da * aplicam família, dos tipos. O uso do arquivo de ajuda da frase "matriz irregular" pode ser um pouco confuso , mas na verdade é bastante simples.
Um vetor:
Um fator (do mesmo comprimento!) Que define grupos:
Adicione os valores em
x
cada subgrupo definido pory
:Exemplos mais complexos podem ser manipulados onde os subgrupos são definidos pelas combinações exclusivas de uma lista de vários fatores.
tapply
é semelhante em espírito à split-aplicar-se combinam funções que são comuns em R (aggregate
,by
,ave
,ddply
, etc.) Daí o seu estatuto ovelha negra.fonte
by
é pura repetição eaggregate
estátapply
em seus núcleos. Eu acho que a ovelha negra faz um excelente tecido.aggregate
eby
também? (Eu finalmente compreendê-los após sua descrição !, mas eles são bastante comuns, por isso pode ser útil para separar e ter alguns exemplos específicos para essas duas funções.)aggregate
, embora ,by
etc. sejam baseados em * funções de aplicação, a maneira como você as utiliza é diferente do ponto de vista dos usuários, devendo ser resumidos em uma resposta separada. Eu posso tentar isso se tiver tempo, ou talvez alguém me derrote e ganhe meu voto positivo.?Map
como um parente demapply
data.frame
s são uma parte absolutamente central de R e, comolist
objeto, são freqüentemente manipulados usandolapply
particularmente. Eles também atuam como contêineres para agrupar vetores / fatores de vários tipos em um conjunto de dados retangular tradicional. Emboradata.table
eplyr
possam adicionar um certo tipo de sintaxe que alguns possam achar mais confortável, eles estão estendendo e agindo emdata.frame
s, respectivamente.Na nota lateral, veja como as várias
plyr
funções correspondem às*apply
funções básicas (da introdução ao documento plyr da página da web plyr http://had.co.nz/plyr/ )Um dos objetivos de
plyr
é fornecer convenções de nomenclatura consistentes para cada uma das funções, codificando os tipos de dados de entrada e saída no nome da função. Ele também fornece consistência na saída, na medida em que a saída dedlply()
é facilmente passávelldply()
para produzir uma saída útil, etc.Conceitualmente, o aprendizado
plyr
não é mais difícil do que entender as*apply
funções básicas .plyr
ereshape
funções substituíram quase todas essas funções no meu uso diário. Mas, também do documento Intro to Plyr:fonte
*apply()
família de funções. Para mim,ddply()
foi muito intuitivo, pois estava familiarizado com as funções de agregação SQL.ddply()
tornou-se meu martelo para resolver muitos problemas, alguns dos quais poderiam ter sido melhor resolvidos com outros comandos.plyr
funções é semelhante a*apply
funções; portanto, se você pode fazer uma, pode fazer a outra, mas asplyr
funções são mais fáceis de lembrar. Mas concordo totalmente com oddply()
martelo!join()
função que executa tarefas semelhantes à mesclagem. Talvez seja mais importante mencioná-lo no contexto de plyr.eapply
vapply
e as desvantagens desapply
. Uma grande vantagemvapply
disso é que ele impõe o tipo e o comprimento da saída, para que você termine com a saída exata exata ou com um erro informativo. Por outro lado,sapply
tentará simplificar a saída seguindo regras que nem sempre são óbvias e, caso contrário, voltará a uma lista. Por exemplo, tentar prever o tipo de saída esta irá produzir:sapply(list(1:5, 6:10, matrix(1:4, 2)), function(x) head(x, 1))
. Que talsapply(list(matrix(1:4, 2), matrix(1:4, 2)), ...)
?No slide 21 da http://www.slideshare.net/hadley/plyr-one-data-analytic-strategy :
(Espero que fique claro que
apply
corresponde a @ Hadleyaaply
eaggregate
a @ Hadley'sddply
etc. O slide 20 do mesmo compartilhamento de slides esclarecerá se você não obtê-lo nesta imagem.)(à esquerda é entrada, na parte superior é saída)
fonte
Primeiro comece com a excelente resposta de Joran - qualquer coisa duvidosa pode melhorar isso.
As seguintes mnemônicas podem ajudar a lembrar as distinções entre cada uma. Enquanto alguns são óbvios, outros podem ser menos - para estes você encontrará justificativa nas discussões de Joran.
Mnemônicos
lapply
é uma lista aplicada que atua em uma lista ou vetor e retorna uma lista.sapply
é simpleslapply
(a função padrão é retornar um vetor ou matriz quando possível)vapply
é uma aplicação verificada (permite que o tipo de objeto de retorno seja pré-especificado)rapply
é uma aplicação recursiva para listas aninhadas, ou seja, listas dentro de listastapply
é uma aplicação marcada onde as tags identificam os subconjuntosapply
é genérico : aplica uma função às linhas ou colunas de uma matriz (ou, geralmente, às dimensões de uma matriz)Construindo o fundo certo
Se o uso da
apply
família ainda parecer um pouco estranho para você, pode ser que você esteja perdendo um ponto de vista fundamental.Esses dois artigos podem ajudar. Eles fornecem o fundo necessário para motivar as técnicas de programação funcional que estão sendo fornecidas pela
apply
família de funções.Os usuários do Lisp reconhecerão o paradigma imediatamente. Se você não estiver familiarizado com o Lisp, depois de entender o FP, você ganhará um ponto de vista poderoso para uso no R - e
apply
fará muito mais sentido.fonte
Desde que percebi que (as muito excelentes) respostas deste post não têm
by
eaggregate
explicações. Aqui está a minha contribuição.DE
A
by
função, conforme declarado na documentação, pode ser um "wrapper" paratapply
. O poder deby
surge quando queremos calcular uma tarefa quetapply
não pode lidar. Um exemplo é este código:Se imprimirmos esses dois objetos,
ct
ecb
"essencialmente" tivermos os mesmos resultados e as únicas diferenças existirão em como elas são mostradas e nos diferentesclass
atributos, respectivamenteby
paracb
earray
paract
.Como eu disse, o poder de
by
surge quando não podemos usartapply
; o código a seguir é um exemplo:R diz que os argumentos devem ter os mesmos comprimentos, diga "queremos calcular a
summary
variável de todas aoiris
longo do fatorSpecies
": mas R simplesmente não pode fazer isso porque não sabe como lidar.Com a
by
função R, despacha um método específico para adata frame
classe e deixa asummary
função funcionar mesmo que o comprimento do primeiro argumento (e o tipo também) seja diferente.funciona de fato e o resultado é muito surpreendente. É um objeto de classe
by
que, ao longoSpecies
(digamos, para cada um deles), calcula o valorsummary
de cada variável.Observe que, se o primeiro argumento for a
data frame
, a função despachada deverá ter um método para essa classe de objetos. Por exemplo, se usarmos esse código com amean
função, teremos esse código que não faz sentido algum:AGREGAR
aggregate
pode ser visto como outro modo de uso diferentetapply
se o usarmos dessa maneira.As duas diferenças imediatas são que o segundo argumento de
aggregate
deve ser uma lista enquantotapply
pode (não obrigatório) ser uma lista e que a saída deaggregate
é um quadro de dados enquanto o detapply
é umarray
.O poder de
aggregate
é que ele pode lidar facilmente com subconjuntos de dados comsubset
argumento e que também possui métodos parats
objetosformula
.Esses elementos
aggregate
facilitam o trabalho com issotapply
em algumas situações. Aqui estão alguns exemplos (disponíveis na documentação):Podemos conseguir o mesmo com,
tapply
mas a sintaxe é um pouco mais difícil e a saída (em algumas circunstâncias) menos legível:Há outros momentos em que não podemos usar
by
outapply
e temos que usaraggregate
.Não podemos obter o resultado anterior com
tapply
uma chamada, mas temos que calcular a média longitudinalMonth
de cada elemento e combiná-los (observe também que precisamos chamar ana.rm = TRUE
, porque osformula
métodos daaggregate
função têm por padrão ana.action = na.omit
):embora with
by
não possamos conseguir isso, na verdade a seguinte chamada de função retorna um erro (mas provavelmente está relacionada à função fornecidamean
):Outras vezes, os resultados são os mesmos e as diferenças são apenas no objeto da classe (e depois como é mostrado / impresso e não apenas - por exemplo, como subconjunto):
O código anterior alcança o mesmo objetivo e resultados; em alguns momentos, qual ferramenta usar é apenas uma questão de gostos e necessidades pessoais; os dois objetos anteriores têm necessidades muito diferentes em termos de subconjunto.
fonte
data.frame(tapply(unlist(iris[,-5]),list(rep(iris[,5],ncol(iris[-5])),col(iris[-5])),summary))
este é um uso do tapply. With the right splitting there is nothing you cant do with
tapply. The only thing is it returns a matrix. Please be careful by saying we cant use
tapply`Há muitas ótimas respostas que discutem diferenças nos casos de uso de cada função. Nenhuma das respostas discute as diferenças de desempenho. Isso é razoável porque várias funções esperam várias entradas e produzem várias saídas, mas a maioria delas tem um objetivo geral comum de avaliar por séries / grupos. Minha resposta vai se concentrar no desempenho. Como acima, a criação de entrada dos vetores é incluída no tempo, também a
apply
função não é medida.Eu testei duas funções diferentes
sum
elength
ao mesmo tempo. O volume testado é de 50M na entrada e 50K na saída. Também incluí dois pacotes atualmente populares que não eram amplamente usados no momento em que a pergunta foi feita,data.table
edplyr
. Definitivamente, vale a pena olhar para ambos se você está buscando um bom desempenho.fonte
Apesar de todas as excelentes respostas aqui, existem mais 2 funções básicas que merecem ser mencionadas, a
outer
função útil e aeapply
função obscuraexterior
outer
é uma função muito útil oculta como mais comum. Se você ler a ajuda paraouter
sua descrição, diz:o que faz parecer que isso só é útil para coisas do tipo álgebra linear. No entanto, pode ser usado de maneira semelhante
mapply
à aplicação de uma função a dois vetores de entradas. A diferença é quemapply
aplicará a função aos dois primeiros elementos e, em seguida, aos dois segundos etc., enquantoouter
aplicará a função a todas as combinações de um elemento do primeiro vetor e um do segundo. Por exemplo:Eu pessoalmente o usei quando tenho um vetor de valores e um vetor de condições e desejo ver quais valores atendem a quais condições.
ansiosamente
eapply
é comolapply
exceto que, em vez de aplicar uma função a todos os elementos de uma lista, ela aplica uma função a todos os elementos de um ambiente. Por exemplo, se você deseja encontrar uma lista de funções definidas pelo usuário no ambiente global:Francamente, eu não uso muito isso, mas se você estiver criando muitos pacotes ou criando muitos ambientes, pode ser útil.
fonte
Talvez valha a pena mencionar
ave
.ave
étapply
primo amigável de. Ele retorna os resultados em um formulário que você pode conectar diretamente ao seu quadro de dados.Não há nada no pacote base que funcione como
ave
para quadros de dados inteiros (comoby
étapply
para quadros de dados). Mas você pode falsificá-lo:fonte
Eu descobri recentemente a
sweep
função bastante útil e a adicionei aqui por uma questão de integridade:varrer
A ideia básica é a de varrer por meio de uma matriz ou row- direcção de coluna e retornar uma matriz modificada. Um exemplo deixará isso claro (fonte: datacamp ):
Digamos que você tenha uma matriz e queira padronizá- la em colunas:
NB: para este exemplo simples, obviamente, o mesmo resultado pode ser alcançado mais facilmente
apply(dataPoints, 2, scale)
fonte
sweep
é uma função de ordem superior, como todas as outras mencionadas aqui, por exemploapply
, Portantosapply
,lapply
a mesma pergunta pode ser feita sobre a resposta aceita com mais de 1.000 votos positivos e os exemplos dados nela. Basta dar uma olhada no exemplo dado porapply
lá.sweep(matrix(1:6,nrow=2),2,7:9,list)
. Geralmente é mais eficiente do queapply
porque ondeapply
loopssweep
é capaz de usar funções vetorizadas.No pacote recolhido recentemente lançado no CRAN, tentei compactar a maioria das funcionalidades comuns de aplicação em apenas 2 funções:
dapply
(Data-Apply) aplica funções a linhas ou (padrão) colunas de matrizes e data.frames e (padrão) retorna um objeto do mesmo tipo e com os mesmos atributos (a menos que o resultado de cada cálculo seja atômico edrop = TRUE
). O desempenho é comparável aolapply
das colunas data.frame e cerca de duas vezes mais rápido queapply
nas linhas ou colunas da matriz. O paralelismo está disponível viamclapply
(apenas para MAC).Sintaxe:
Exemplos:
BY
é um S3 genérico para computação de combinação e aplicação dividida com o vetor, matriz e método data.frame. É significativamente mais rápido quetapply
,by
eaggregate
(também mais rápido queplyr
em grandes dadosdplyr
é mais rápido).Sintaxe:
Exemplos:
Também podem ser fornecidas listas de variáveis de agrupamento para
g
.Falando sobre desempenho: O principal objetivo do colapso é promover a programação de alto desempenho no R e ir além da combinação de aplicar e dividir. Para este efeito, o pacote tem um conjunto completo de C ++ com base funções rápido genéricos:
fmean
,fmedian
,fmode
,fsum
,fprod
,fsd
,fvar
,fmin
,fmax
,ffirst
,flast
,fNobs
,fNdistinct
,fscale
,fbetween
,fwithin
,fHDbetween
,fHDwithin
,flag
,fdiff
efgrowth
. Eles executam cálculos agrupados em uma única passagem pelos dados (ou seja, sem divisão e recombinação).Sintaxe:
Exemplos:
Nas vinhetas da embalagem, forneço referências. A programação com as funções rápidas é significativamente mais rápida que a programação com dplyr ou data.table , especialmente em dados menores, mas também em dados grandes.
fonte