2017-12-26 181 views
6

Rozważmy następujący przykład: jest wyświetlanywyświetlacz wykreślono dane tylko w legendzie

library(ggplot2) 
df = data.frame(x = 1:5, y = 1:5, z = c('a', 'a', 'a', 'b', 'b')) 

ggplot(df, aes(x, y, col = z)) + geom_line() + geom_point() + 
    coord_cartesian(xlim = c(1, 2.5)) 

enter image description here

jedynie dane z a wiadra, ale zarówno a i b pojawiają się w legendzie. Jak mogę to naprawić, aby w legendzie pojawił się tylko ten, który został faktycznie wydrukowany?

Dla kontekstu - napotykam to podczas próby zooming into plots w shiny.

+0

Jeśli masz punkty poza widocznym obszarem kreślenia, co ma miejsce w przypadku powiększania, wówczas pokazywanie wszystkich różnych klas punktów jest domyślnym zachowaniem. – Heikki

+3

@ Heikki haha, ok, nie jest to pożądane przeze mnie - w ten sposób pytanie – eddi

+1

możesz użyć tego, co zostało zwrócone przez 'shiny', aby przefiltrować dane, zamiast określać je za pomocą' coord_cartesian' – bouncyball

Odpowiedz

5

Czy filtrowanie na z obejmuje rzeczywisty przypadek użycia? Na przykład:

library(tidyverse) 

df = data.frame(x = 1:5, y = 1:5, z = c('a', 'a', 'a', 'b', 'b')) 

ggplot(df %>% filter(z %in% z[between(x,1,2.5)]), 
     aes(x, y, col = z)) + 
    geom_line() + geom_point() + 
    coord_cartesian(xlim = c(1, 2.5)) 

Lub w funkcji, która może być dodatkowo uogólniona dla wprowadzonych przez użytkownika zmiennych estetycznych. (Ja również zaktualizowane funkcję użyć interpolacji do wykreślenia linii nawet w regionach fabuły, które zawierają żadnych punktów danych, o ile przynajmniej jedna linia łącząca pomiędzy punktami przebiega przez region plot.)

my_plot = function(xrng, data=df, step=0.01) { 

    levs = unique(data[["z"]]) 
    n = length(levs) 

    # Generate interpolated data frame so we can plot lines even if 
    # no points appear in the graph region 
    dat_interp = split(data, data$z) %>% 
    map_df(function(d) { 
     x = seq(min(d$x), max(d$x), step) 
     data.frame(z=rep(unique(d$z), each=length(x)), 
       x, y=rep(approx(d$x, d$y, xout=x)$y, n)) 
    }) 

    ggplot(dat_interp %>% filter(z %in% z[between(x,xrng[1],xrng[2])]), 
     aes(x, y, col = z)) + 
    geom_point(data=data %>% filter(z %in% z[between(x,xrng[1],xrng[2])])) + 
    geom_line() + 
    coord_cartesian(xlim = xrng) + 
    scale_color_manual(values=setNames(hcl(seq(15,375,length=n+1)[1:n],100,65), levs)) 
} 


gridExtra::grid.arrange(
    my_plot(c(1,2.5)), 
    my_plot(c(1,4)), 
    my_plot(c(3,4)), 
    my_plot(c(4.3,6)), 
    my_plot(c(1.1,1.6)), 
    my_plot(c(4.2,4.9))) 

enter image description here

+0

Dzięki! Po pewnym kliknięciu - nie dotyczy to przypadku 'my_plot (c (1.1, 1.6)), ale jest to dla mnie wystarczająco dobre rozwiązanie. – eddi

+1

Zaktualizowałem odpowiedź, aby użyć interpolacji, aby poradzić sobie z przypadkiem braku punktów danych w obszarze wykresu. – eipi10