2015-04-30 8 views
10

chcę mieć zarówno month i day w osi x-ów z serii działce czasu podczas korzystania facet lat w ggplot2. Moja MWE jest poniżej:daty z miesiąc i dzień w serii działce czasu w ggplot2 z obwódką na lata

set.seed(12345) 
Date <- seq(as.Date("2010/1/1"), as.Date("2014/1/1"), "week") 
Y <- rnorm(n=length(Date), mean=100, sd=1) 
df <- data.frame(Date, Y) 

df$Year <- format(df$Date, "%Y") 
df$Month <- format(df$Date, "%b") 
df$Day <- format(df$Date, "%d") 

df$MonthDay <- format(df$Date, "%d-%b") 


p <- ggplot(data=df, mapping=aes(x=MonthDay, y=Y, shape=Year, color=Year)) + geom_point() +geom_line(aes(group = 1)) 
p <- p + facet_grid(facets = Year ~ ., margins = FALSE) + theme_bw() 
print(p) 

enter image description here

Starałem się kontrolować etykiety osi x za pomocą następującego polecenia

p + scale_y_continuous() + scale_x_date(labels = date_format("%d-%b")) 

Ale to rzuca się następujący komunikat o błędzie.

Error: Invalid input: date_trans works with objects of class Date only 

Każda pomoc w rozwiązaniu tego problemu będzie bardzo cenna. Z góry dziękuje za twoją pomoc.

+0

Dzięki @ G.Grothendieck za komentarz i zainteresowanie moim problemem. Użycie 'x = Date' będzie niepotrzebnie przez wszystkie cztery lata w osi X, co nie jest wymagane. – MYaseen208

Odpowiedz

16

Jesteś bardzo blisko. Chcesz, aby oś X była miarą miejsca w roku, w którym się znajdujesz, ale masz ją jako wektor znaków i dlatego każdy pojedynczy punkt jest oznaczony etykietą. Jeśli zamiast tego tworzysz zmienną ciągłą, to możesz mieć lepsze wyniki. Jedną zmienną ciągłą byłby dzień roku.

df$DayOfYear <- as.numeric(format(df$Date, "%j")) 
ggplot(data = df, 
     mapping = aes(x = DayOfYear, y = Y, shape = Year, colour = Year)) + 
    geom_point() + 
    geom_line() + 
    facet_grid(facets = Year ~ .) + 
    theme_bw() 

enter image description here

Oś może zostać sformatowany więcej Date-jak z odpowiedniej funkcji etykiet, ale przerwy wciąż nie znaleziono w datę świadomy sam sposób. (A na dodatek, nie ma problemu NA również.)

ggplot(data = df, 
     mapping = aes(x = DayOfYear, y = Y, shape = Year, colour = Year)) + 
    geom_point() + 
    geom_line() + 
    facet_grid(facets = Year ~ .) + 
    scale_x_continuous(labels = function(x) format(as.Date(as.character(x), "%j"), "%d-%b")) + 
    theme_bw() 

enter image description here

Aby uzyskać dobroć przyjemnych dat przerw inna zmienna może być używany. Jeden ma ten sam dzień w roku co oryginalne dane, ale tylko jeden rok. W tym przypadku 2000, ponieważ był to rok przestępny. Problemy z tym mają głównie związek z dniami przestępnymi, ale jeśli nie dbasz o to (1 marca roku, który nie był przestępny, byłby zgodny z 29 lutego roku przestępnego itp.) Można użyć:

df$CommonDate <- as.Date(paste0("2000-",format(df$Date, "%j")), "%Y-%j") 
ggplot(data = df, 
     mapping = aes(x = CommonDate, y = Y, shape = Year, colour = Year)) + 
    geom_point() + 
    geom_line() + 
    facet_grid(facets = Year ~ .) + 
    scale_x_date(labels = function(x) format(x, "%d-%b")) + 
    theme_bw() 

enter image description here

+0

Doskonała odpowiedź. @Brian, posiadanie codziennych danych przez kilka lat i pragnienie spiskich lat na sobie, wydaje mi się bardzo częstym zadaniem. Czy znasz jakiś pakiet, który pobiera zmienną daty, używa podejścia "CommonDate" bez problemu dni przestępnych? – Dan

+1

@Dan Przepraszamy, nie znam pakietu, który to robi. Jest kilka częściowych dat/częściowych czasów, które byłyby użyteczne w takich kontekstach, ale nie znam żadnego miejsca, w którym zostałyby zebrane. –

3

Wydaje się to zrobić ... po prostu ręcznie stworzone etykiety ...

library("ggplot2") 
library("scales") 
set.seed(12345) 
Date <- seq(as.Date("2010/1/1"), as.Date("2014/1/1"), "week") 
Y <- rnorm(n=length(Date), mean=100, sd=1) 
df <- data.frame(Date, Y) 

df$Year <- format(df$Date, "%Y") 
df$Month <- format(df$Date, "%b") 
df$Day <- format(df$Date, "%d") 

df$MonthDay <- format(df$Date, "%d-%b") 
df$MonthDay2 <- df$MonthDay 
# only show every third label... otherwise it's too crowded 
df$MonthDay2[as.numeric(row.names(df))%%3!=0] <- "" 
labels <- df$MonthDay2 

p <- ggplot(data=df, mapping=aes(x=MonthDay, y=Y, shape=Year, color=Year)) + geom_point() +geom_line(aes(group = 1)) 
p <- p + facet_grid(facets = Year ~ ., margins = FALSE) + theme_bw() 
p + scale_y_continuous() + scale_x_discrete(labels=labels) + 
    theme(axis.text.x = element_text(angle = 90, vjust = 0.5, size = 8)) 

plot

+0

Dzięki @cory za dobre rozwiązanie. (+1) – MYaseen208

+1

ktokolwiek inny dostaje złe daty? Mam wszystko przekonwertowane na 2015 .. – infominer

+0

Doskonały wybór @infominer. – MYaseen208

6

Kłucie z kodem @ MYaseen208 do tworzenia danych.

Kiedy wykreślić go używać x = Date i użyj poniżej

p <- ggplot(data = df, aes(x = Date, y = Y, shape = Year, color = Year)) + 
    geom_point() + geom_line(aes(group = 1)) 
    #adding facet and using facet_wrap with free x scales 
    p <- p + facet_wrap(~Year,ncol=1, scales = "free_x") + theme_bw()+ 
scale_y_continuous() + 
scale_x_date(labels = date_format("%d-%b"), breaks = date_breaks("2 weeks")) + 
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, size = 8)) 

użyłem facet_wrap, aby uzyskać bezpłatne łuski x_axis. Kiedy dzielisz dane, nie możemy uzyskać tej samej kombinacji dzień-miesiąc dla każdego roku.

enter image description here

0

Modyfikacja podejścia @Brian Diggs', który zachowuje oryginalną dzień i miesiąc (01 marca jest zachowana jako 1 marca zamiast 29 lutego) jest do zmuszania datę na ciąg znaków, a następnie zastąpić roku:

library(lubridate) 
library(stringr) 
df$CommonDate <- ymd(paste0("2000-",str_sub(as.character(df$Date),-5))) 

następnie można kontynuować:

ggplot(data = df, 
    mapping = aes(x = CommonDate, y = Y, shape = Year, colour = Year)) + 
    geom_point() + 
    geom_line() + 
    facet_grid(facets = Year ~ .) + 
    scale_x_date(labels = function(x) format(x, "%d-%b")) + 
    theme_bw() 
Powiązane problemy