2012-05-09 12 views
12

muszę stworzyć prosty liniowy wykres z grup, stosując następujące dane:Jak utworzyć wykres liniowy z grupami w Base R bez pętli?

test = data.frame(x = rep(1:3, each = 2), 
        group = rep(c("Group 1","Group 2"),3), 
        groupcd= rep(c(1,2),3), 
        y= c(22,8,11,4,7,5) 
       ) 

można łatwo zrobić z ggplot:

library(ggplot2) 
    #GGPLOT 
    qplot(x=x, y=y, 
      data=test, 
      colour=group, 
      main="GGPLOT line plot with groups") + 
     geom_line() 

enter image description here

Mogę też zrobić to z TRELLIS:

library(lattice) 
xyplot(y~x, 
     type="b", 
     group=group, 
     data=test, 
     main="TRELLIS line plot with groups", 
     auto.key =list(
     lines = TRUE) 
     ) 

enter image description here

Jednak jestem trochę niechętny do korzystania z GGPLOT lub TRELLIS już teraz. Chciałbym być w stanie stworzyć ten wykres z podstawą R. jedyny sposób mogę dostać tę działkę do pracy w bazie R jest za pomocą pętli for:

# set up empty plot 
plot(test$y ~test$x, ylab="y", xlab="x", type="n", main="Base R line plot with groups") 
colors<-c("red","blue") 
#plot each group in the for loop 
number_of_groups <- as.numeric(max(unique(test$groupcd))) #calculate number of groups 
for (i in 1:number_of_groups) 
{ 
    temp <- subset(test, groupcd==i) 
    lines(temp$x, temp$y, col=colors[i]) 
    points(temp$x, temp$y, col=colors[i]) 
} 
legend("top", legend=unique(test$group), text.col =colors ) 

enter image description here

Takie podejście wydaje się dość zwinięty. Czy jest łatwiejszy sposób na zrobienie tego w bazie R? Czy istnieje opcja grupowa w podstawowej funkcji fabuły? Dziękuję bardzo.

+4

przekształć dane w formacie szerokokątnym i użyj 'matplot' ... –

+0

Dziękuję bardzo! Nie wiedziałem nawet o matplot - jest to niezwykle pomocne. Jest to bardzo dobre rozwiązanie i wydaje się najlepszym rozwiązaniem. Jestem po prostu zaskoczony, że grupowanie nie może być łatwe z PLOT. Jeszcze raz dziękuję –

+0

Myślę, że powinieneś przesłać swoje rozwiązanie 'matplot' jako odpowiedź, a nie jako odpowiedź na twoje pytanie (chociaż w zależności od twojej reputacji możesz potrzebować trochę poczekać - nie wiem). Myślę, że mogę śmiało powiedzieć, że nie ma * prostej * opcji grupowej w 'bazie :: spisek '.Kilka innych myśli na temat twojego kodu powyżej: (1) Myślę, że możesz użyć 'subset (test_transposed, select = -x)', aby upuścić kolumnę 'x'; (2) prawdopodobnie chcesz "lty = 1: 2, col = kolory, pch = 1: 2" w twoim "legendzie". –

Odpowiedz

8

Co o czymś takim jako baza do pracy z:

test = data.frame(x = rep(1:3, each = 2), 
        group = rep(c("Group 1","Group 2"),3), 
        groupcd= rep(c(1,2),3), 
        y= c(22,8,11,4,7,5) 
       ) 

xvals <- split(test$x,test$group) 
yvals <- split(test$y,test$group) 

plot(1:max(unlist(xvals)),ylim=(c(0,max(unlist(yvals)))),type="n") 
# thanks to @BenBolker for refining this next key line 
mapply(lines,xvals,yvals,col=c("red","blue"),pch=1:2,type="o") 

Wynik:

enter image description here

+0

To jest genialne podejście. Czy jednak nie jest to zmiana w podejściu pętli? tj. nie ma zmiennej "grupującej", takiej jak ta na wykresie TRELLIS. Za chwilę przedstawię rozwiązanie matplot jako odpowiedź. Nie udaje mi się zmienić R, aby zdecydować, które podejście jest lepsze. –

+0

Dzięki, ale może to być przedwczesna pochwała. Nie wiem, jak przekazać wektor kolorów w instrukcji 'mapply', aby każda linia nie wyglądała tak samo. Musi być możliwe, ale może sprawić, że to "proste" rozwiązanie będzie znów złożone. – thelatemail

+0

Jest to dość rozszerzalne rozwiązanie, np. 'mapply (linie, xvals, yvals, col = c (" czerwony "," niebieski "), lty = 1: 2, pch = 1: 2, MoreArgs = list (type =" b "))' - all the argumenty zostają wektoryzowane ponad * z wyjątkiem * tych w 'MoreArgs' –

2

innego podejścia z wykorzystaniem MATPLOT:

library(reshape) 
test = data.frame(x = rep(1:3, each = 2), 
        group = rep(c("Group 1","Group 2"),3), 
        groupcd= rep(c(1,2),3), 
        y= c(22,8,11,4,7,5) 
       ) 
colors<-c("red","blue") 

#Transform data to wide format 
test_transposed<-reshape(test, 
         idvar='x', 
         drop="group", 
         timevar="groupcd", 
         direction="wide") 
colors<-c("red","blue") 

#drop x column 
test_transposed$x<-NULL 

matplot(test_transposed, 
     type = "b", 
     ylab="y", 
     col=colors, 
     main="MATPLOT with groups", 
     pch = 1:2) 

legend("top", 
     legend=unique(test$group), 
     lty=1:2, 
     col=colors, 
     pch=1:2 ) 

enter image description here

1

Zastanawiam się również nad tym. Moje dane paneli nie mają pełnego zasięgu na osi X (w latach), więc rozwiązania podobne do macierzy byłyby prawdopodobnie skomplikowane. Zamiast tego poszedłem z ...

mytest = data.frame(
       x = rep(1:3, each = 2), 
       groupcd= rep(c(1,2),3), 
       y= c(22,8,11,4,7,5) 
      ) 
mytest = rbind(mytest,c(2,3,15),c(3,3,17)) 

plottables <- split(mytest,mytest$groupcd) 
plot(y~x,dat=plottables[[1]],type="l",xlim=range(mytest$x),ylim=range(mytest$y)) 
lapply(plottables,function(z)points(y~x,dat=z,type="l")) 
0

Chciałbym przedłużyć trochę ten post..suppose że instad o wykreślenie linii chcę linii regresji. Rozszerzanie kodu @Frank ..

mytest = data.frame(
       x = rep(1:3, each = 2), 
       groupcd= rep(c(1,2),3), 
       y= c(22,8,11,4,7,5) 
      ) 
mytest = rbind(mytest,c(2,3,15),c(3,3,17)) 

    plottables <- split(mytest,mytest$groupcd) 
plot(y~x,dat=plottables[[1]],type="n",xlim=range(mytest$x),ylim=range(mytest$y)) 
lapply(plottables,function(z)points(z$x, z$y)) 
lapply(plottables,function(z)lines(z$x, predict(lm(z$y ~ z$x), list(z$x)))) 

Teraz załóżmy, że chcę również zmienić kolory dla każdego poziomu grupy. Próbowałem podejście zaproponowane przez @BenBolker

xvals <- tapply(mytest$x, mytest$groupcd, function(x) return(x)) 
    yvals <- tapply(mytest$y, mytest$groupcd, function(x) return(x)) 

    plot(1:max(unlist(xvals)),ylim=(c(0,max(unlist(yvals)))),type="n") 
    mapply(points, xvals, yvals, bg=c(1:3),pch=21,type="p") 
    mapply(lines(xvals, predict(lm(yvals ~ xvals), list(xvals)), col = c(1:3))) 

des ale nie działa.

Powiązane problemy