Preciso plotar um gráfico de barras mostrando contagens e um gráfico de linhas mostrando a taxa em um gráfico, posso fazer os dois separadamente, mas quando os uno, a escala da primeira camada (ou seja, a geom_bar
) é sobreposta pela segunda camada (ou seja, o geom_line
).
Posso mover o eixo do geom_line
para a direita?
ggplot2
implementação nativascale_y_*
, atualmente chamadasec.axis
.Respostas:
Às vezes, um cliente quer duas escalas y. Dar-lhes o discurso "defeituoso" é muitas vezes inútil. Mas eu gosto da insistência do ggplot2 em fazer as coisas da maneira certa. Estou certo de que o ggplot está de fato educando o usuário médio sobre as técnicas de visualização adequadas.
Talvez você possa usar o facetamento e a escala livre para comparar as duas séries de dados? - por exemplo, veja aqui: https://github.com/hadley/ggplot2/wiki/Align-two-plots-on-a-page
fonte
Não é possível no ggplot2 porque acredito que plotagens com escalas y separadas (não escalas y que são transformações umas das outras) são fundamentalmente defeituosas. Alguns problemas:
Não são invertíveis: dado um ponto no espaço da plotagem, você não pode mapeá-lo exclusivamente de volta a um ponto no espaço de dados.
Eles são relativamente difíceis de ler corretamente em comparação com outras opções. Consulte Um estudo sobre gráficos de dados em dupla escala de Petra Isenberg, Anastasia Bezerianos, Pierre Dragicevic e Jean-Daniel Fekete para obter detalhes.
Eles são facilmente manipulados para enganar: não há uma maneira única de especificar as escalas relativas dos eixos, deixando-as abertas à manipulação. Dois exemplos do blog Junkcharts: um , dois
Eles são arbitrários: por que ter apenas 2 escalas, não 3, 4 ou dez?
Você também pode ler a longa discussão de Stephen Few sobre o tópico Eixos de dupla escala em gráficos Eles são sempre a melhor solução? .
fonte
A partir do ggplot2 2.2.0, você pode adicionar um eixo secundário como este (retirado do anúncio do ggplot2 2.2.0 ):
fonte
Tomando as respostas acima e alguns ajustes (e para o que vale a pena), aqui está uma maneira de obter duas escalas através de
sec_axis
:Suponha um conjunto de dados simples (e puramente fictício)
dt
: por cinco dias, ele rastreia o número de interrupções na produtividade VS:(os intervalos de ambas as colunas diferem aproximadamente pelo fator 5).
O código a seguir desenhará as duas séries que eles usam todo o eixo y:
Aqui está o resultado (código acima + alguns ajustes de cores):
O ponto (além de usar
sec_axis
ao especificar a escala y_ é multiplicar cada valor da 2ª série de dados por 5 ao especificar a série. Para obter os rótulos corretos na definição sec_axis, é necessário dividir por 5 (e formatação). uma parte crucial no código acima está realmente*5
na geom_line e~./5
na sec_axis (uma fórmula que divide o valor atual.
por 5).Em comparação (não quero julgar as abordagens aqui), é assim que dois gráficos um sobre o outro se parecem:
Você pode julgar por si mesmo qual deles melhor transporta a mensagem (“Não perturbe as pessoas no trabalho!”). Acho que é uma maneira justa de decidir.
O código completo para ambas as imagens (não é realmente mais do que o que está acima, apenas está completo e pronto para ser executado) está aqui: https://gist.github.com/sebastianrothbucher/de847063f32fdff02c83b75f59c36a7d uma explicação mais detalhada aqui: https: // sebastianrothbucher. github.io/datascience/r/visualization/ggplot/2018/03/24/two-scales-ggplot-r.html
fonte
Existem casos de uso comuns em eixos de duelo, por exemplo, o climatógrafo mostrando a temperatura e a precipitação mensais. Aqui está uma solução simples, generalizada da solução da Megatron, permitindo que você defina o limite inferior das variáveis para algo diferente de zero:
Dados de exemplo:
Defina os dois valores a seguir para valores próximos aos limites dos dados (você pode brincar com eles para ajustar as posições dos gráficos; os eixos ainda estarão corretos):
A seguir, são feitos os cálculos necessários com base nesses limites e o próprio gráfico:
Se você deseja garantir que a linha vermelha corresponda ao eixo y do lado direito, você pode adicionar uma
theme
frase ao código:que pinta o eixo da direita:
fonte
ylim.prim
eylim.sec
.Você pode criar um fator de escala que é aplicado ao segundo geom e ao eixo y direito. Isso é derivado da solução de Sebastian.
Nota: usando a
ggplot2
v3.0.0fonte
A espinha dorsal técnica da solução desse desafio foi fornecida por Kohske há cerca de 3 anos [ KOHSKE ]. O tópico e os detalhes técnicos em torno de sua solução foram discutidos em várias instâncias aqui no Stackoverflow [IDs: 18989001, 29235405, 21026598]. Portanto, fornecerei apenas uma variação específica e algumas orientações explicativas, usando as soluções acima.
Vamos supor que temos alguns dados y1 no grupo G1 aos quais alguns dados y2 no grupo G2 estão relacionados de alguma forma, por exemplo, faixa / escala transformada ou com algum ruído adicionado. Então, alguém deseja plotar os dados juntos em um gráfico com a escala de y1 à esquerda e y2 à direita.
Se agora traçarmos nossos dados junto com algo como
ele não se alinha bem quando a escala menor y1 é obviosamente colapsada pela escala maior y2 .
O truque aqui para enfrentar o desafio é plotar tecnicamente os dois conjuntos de dados na primeira escala y1, mas reportar o segundo em um eixo secundário com rótulos que mostram a escala original y2 .
Por isso, criamos uma primeira função auxiliar CalcFudgeAxis que calcula e coleta recursos do novo eixo a ser mostrado. A função pode ser alterada ao gosto de todos (este apenas mapeia y2 no intervalo de y1 ).
o que produz alguns:
Agora, envolvi a solução de Kohske na segunda função auxiliar PlotWithFudgeAxis (na qual lançamos o objeto ggplot e o objeto auxiliar do novo eixo):
Agora, tudo pode ser reunido: O código abaixo mostra como a solução proposta pode ser usada no ambiente do dia a dia . A chamada de plotagem agora não plota mais os dados originais y2, mas uma versão clonada yf (mantida dentro do objeto auxiliar pré-calculado FudgeAxis ), que roda na escala de y1 . O objeto ggplot original é então manipulado com a função auxiliar de Kohske , PlotWithFudgeAxis, para adicionar um segundo eixo preservando as escalas de y2 . Plota também o enredo manipulado.
Agora, isso é plotado conforme desejado com dois eixos, y1 à esquerda e y2 à direita
A solução acima é, para esclarecer, um hack limitado e instável. Ao jogar com o kernel do ggplot, ele emitirá alguns avisos de que trocamos escalas pós-fatos, etc. Ele deve ser manuseado com cuidado e pode gerar algum comportamento indesejável em outro ambiente. Também pode ser necessário mexer nas funções auxiliares para obter o layout conforme desejado. O posicionamento da legenda é um problema (seria colocado entre o painel e o novo eixo; é por isso que eu o soltei). A escala / alinhamento do eixo 2 também é um pouco desafiadora: o código acima funciona muito bem quando as duas escalas contêm o "0", caso contrário, um eixo é deslocado. Definitivamente, com algumas oportunidades para melhorar ...
No caso de querer salvar a foto, é necessário agrupar a chamada no dispositivo para abrir / fechar:
fonte
O artigo a seguir me ajudou a combinar dois gráficos gerados pelo ggplot2 em uma única linha:
Vários gráficos em uma página (ggplot2) do Cookbook for R
E aqui está a aparência do código neste caso:
fonte
multiplot
stackoverflow.com/a/51220506Para mim, a parte complicada foi descobrir a função de transformação entre os dois eixos. Eu usei o myCurveFit para isso.
Localizando a Função de Transformação
função de transformação:
f(y1) = 0.025*x + 2.75
função de transformação:
f(y1) = 40*x - 110
Plotagem
Observe como as funções de transformação são usadas na
ggplot
chamada para transformar os dados "on-the-fly"A primeira
stat_summary
chamada é a que define a base para o primeiro eixo y. A segundastat_summary
chamada é chamada para transformar os dados. Lembre-se de que todos os dados terão como base o primeiro eixo y. Portanto, esses dados precisam ser normalizados para o primeiro eixo y. Para fazer isso, uso a função de transformação nos dados:y=packetOkSinr*40 - 110
Agora, para transformar o segundo eixo I usar a função oposta dentro da
scale_y_continuous
chamada:sec.axis=sec_axis(~.*0.025+2.75, name="y_second")
.fonte
coef(lm(c(-70, -110) ~ c(1,0)))
ecoef(lm(c(1,0) ~ c(-70, -110)))
. Você pode definir uma função auxiliar tais comoequationise <- function(range = c(-70, -110), target = c(1,0)){ c = coef(lm(target ~ range)) as.formula(substitute(~ a*. + b, list(a=c[[2]], b=c[[1]]))) }
Definitivamente, poderíamos construir um gráfico com dois eixos Y usando a função R de base
plot
.fonte
Você pode usar
facet_wrap(~ variable, ncol= )
em uma variável para criar uma nova comparação. Não está no mesmo eixo, mas é semelhante.fonte
Eu reconheço e concordo com hadley (e outros), que escalas y separadas são "fundamentalmente defeituosas". Dito isto - desejo muitas vezes
ggplot2
ter o recurso - particularmente quando os dados estão em formato amplo e quero rapidamente visualizar ou verificar os dados (ou seja, apenas para uso pessoal).Embora a
tidyverse
biblioteca facilite a conversão de dados em formato longo (para quefacet_grid()
funcione), o processo ainda não é trivial, como mostrado abaixo:fonte
sec_axis
.A resposta de Hadley fornece uma referência interessante ao relatório de Stephen Few. Os eixos de dupla escala em gráficos são sempre a melhor solução? .
Não sei o que significa o OP com "contagens" e "taxa", mas uma pesquisa rápida me fornece contagens e taxas , por isso recebo alguns dados sobre acidentes no montanhismo norte-americano 1 :
E então eu tentei fazer o gráfico como poucos sugeriram na página 7 do relatório mencionado (e seguindo a solicitação do OP para representar graficamente as contagens como um gráfico de barras e as taxas como um gráfico de linhas):
E este é o resultado:
Mas eu não gosto muito e não sou capaz de facilmente colocar uma lenda nele ...
1 WILLIAMSON, Jed, et al. Acidentes no alpinismo norte-americano em 2005. The Mountaineers Books, 2005.
fonte
Parece ser uma pergunta simples, mas confunde cerca de duas questões fundamentais. A) Como lidar com dados multi-escalares enquanto apresenta em um gráfico comparativo e, em segundo lugar, B) se isso pode ser feito sem algumas práticas básicas de programação R, como i) fusão de dados, ii) facetas, iii) adição de outra camada para a existente. A solução fornecida abaixo satisfaz as condições acima, pois lida com os dados sem precisar redimensioná-los e, em segundo lugar, as técnicas mencionadas não são utilizadas.
Aqui está o resultado,
Para os interessados em saber mais sobre esse método, siga o link abaixo. Como plotar um gráfico de eixos y com barras lado a lado sem redimensionar os dados
fonte
Achei que essa resposta me ajudou muito, mas achei que havia alguns casos extremos que não pareciam lidar corretamente, em casos negativos, e também o caso em que meus limites tinham distância 0 (o que pode acontecer se estivermos agarrando nossos limites de max / min de dados). O teste parece indicar que isso funciona consistentemente
Eu uso o seguinte código. Aqui presumo que tenhamos [x1, x2] que queremos transformar em [y1, y2]. A maneira como lidei com isso foi transformar [x1, x2] em [0,1] (um transformaton simples o suficiente), depois [0,1] em [y1, y2].
As partes principais aqui são que transformamos o eixo y secundário
~((.-ylim.prim[1]) *b + ylim.sec[1])
e depois aplicamos o inverso aos valores reaisy = ylim.prim[1]+(Temp-ylim.sec[1])/b)
. Também devemos garantir issolimits = ylim.prim
.fonte