Вопрос по ggplot2, r – Понимание дат и построение гистограммы с помощью ggplot2 в R

56
Main Question

У меня возникли проблемы с пониманием того, почему обработка дат, меток и разрывов не работает так, как я ожидал в R при попытке создать гистограмму с помощью ggplot2.

I'm looking for:

A histogram of the frequency of my dates Tick marks centered under the matching bars Date labels in %Y-b format Appropriate limits; minimized empty space between edge of grid space and outermost bars

Я & APOS; везагрузил мои данные в pastebin сделать это воспроизводимым. Я создал несколько столбцов, поскольку я не был уверен, что это лучший способ сделать это:

> dates <- read.csv("http://pastebin.com/raw.php?i=sDzXKFxJ", sep=",", header=T)
> head(dates)
       YM       Date Year Month
1 2008-Apr 2008-04-01 2008     4
2 2009-Apr 2009-04-01 2009     4
3 2009-Apr 2009-04-01 2009     4
4 2009-Apr 2009-04-01 2009     4
5 2009-Apr 2009-04-01 2009     4
6 2009-Apr 2009-04-01 2009     4

Вот что я попробовал:

library(ggplot2)
library(scales)
dates$converted <- as.Date(dates$Date, format="%Y-%m-%d")

ggplot(dates, aes(x=converted)) + geom_histogram()
+      opts(axis.text.x = theme_text(angle=90))

Который даетэтот график, я хотел%Y-%b форматирование, тем не менее, поэтому я охотился вокруг и попробовал следующее, основываясь наэто ТАК:

ggplot(dates, aes(x=converted)) + geom_histogram()
+    scale_x_date(labels=date_format("%Y-%b"),
+    breaks = "1 month")
+    opts(axis.text.x = theme_text(angle=90))

stat_bin: binwidth defaulted to range/30. Use 'binwidth = x' to adjust this.

Это дает мнеэтот график

Correct x axis label format The frequency distribution has changed shape (binwidth issue?) Tick marks don't appear centered under bars The xlims have changed as well

Я работал с примером вggplot2 документация наscale_x_date раздел иgeom_line() кажется, правильно размечается, помечается и центрируется, когда я использую его с теми же данными оси X. Я не понимаю, почему гистограмма отличается.

Updates based on answers from edgester and gauden

Сначала я думал, что ответ Гаудена помог мне решить мою проблему, но теперь я озадачен, если присмотреться поближе. Обратите внимание на различия между двумя ответами & apos; результирующие графики после кода.

Предположим для обоих:

library(ggplot2)
library(scales)
dates <- read.csv("http://pastebin.com/raw.php?i=sDzXKFxJ", sep=",", header=T)

Основываясь на ответе @dgeter'а ниже, я смог сделать следующее:

freqs <- aggregate(dates$Date, by=list(dates$Date), FUN=length)
freqs$names <- as.Date(freqs$Group.1, format="%Y-%m-%d")

ggplot(freqs, aes(x=names, y=x)) + geom_bar(stat="identity") +
       scale_x_date(breaks="1 month", labels=date_format("%Y-%b"),
                    limits=c(as.Date("2008-04-30"),as.Date("2012-04-01"))) +
       ylab("Frequency") + xlab("Year and Month") +
       theme_bw() + opts(axis.text.x = theme_text(angle=90))

Вот моя попытка, основанная на ответе Гаудена:

dates$Date <- as.Date(dates$Date)
ggplot(dates, aes(x=Date)) + geom_histogram(binwidth=30, colour="white") +
       scale_x_date(labels = date_format("%Y-%b"),
                    breaks = seq(min(dates$Date)-5, max(dates$Date)+5, 30),
                    limits = c(as.Date("2008-05-01"), as.Date("2012-04-01"))) +
       ylab("Frequency") + xlab("Year and Month") +
       theme_bw() + opts(axis.text.x = theme_text(angle=90))

График, основанный на подходе кратера:

edgester-plot

График, основанный на подходе Гаудена:

gauden-plot

Обратите внимание на следующее:

gaps in gauden's plot for 2009-Dec and 2010-Mar; table(dates$Date) reveals that there are 19 instances of 2009-12-01 and 26 instances of 2010-03-01 in the data edgester's plot starts at 2008-Apr and ends at 2012-May. This is correct based on a minimum value in the data of 2008-04-01 and a max date of 2012-05-01. For some reason gauden's plot starts in 2008-Mar and still somehow manages to end at 2012-May. After counting bins and reading along the month labels, for the life of me I can't figure out which plot has an extra or is missing a bin of the histogram!

Есть мысли о различиях здесь? способ создания отдельного счетчика

Related References

Кроме того, вот другие места, которые имеют информацию о датах и ggplot2 для прохожих, ищущих помощи:

Started here at learnr.wordpress, a popular R blog. It stated that I needed to get my data into POSIXct format, which I now think is false and wasted my time. Another learnr post recreates a time series in ggplot2, but wasn't really applicable to my situation. r-bloggers has a post on this, but it appears outdated. The simple format= option did not work for me. This SO question is playing with breaks and labels. I tried treating my Date vector as continuous and don't think it worked so well. It looked like it was overlaying the same label text over and over so the letters looked kind of odd. The distribution is sort of correct but there are odd breaks. My attempt based on the accepted answer was like so (result here).
@ gsk3 Я слышал об этом, хотя, насколько я понимаю, он помогает с форматированием, интервалами, увеличением и т. д. Как вы думаете, моя проблема заключается в том, что lubridate поможет? Я понял, что это было с синтаксисом использования ggplot2 правильно. Hendy
Проверьтеlubridate пакет. Ari B. Friedman
Пожалуйста, задайте новый вопрос, потому что вы просто переключили свой набор данных с оригинала. Этот вопрос очень запутанный для чтения. Пожалуйста, примите ответ и подтвердите любые ответы, которые были полезны. edgester
Я не понимаю вашего вопроса. Вы пытались задать вопрос, а затем ответить на него в том же посте? Если это так, пожалуйста, перефразируйте свой вопрос как вопрос, а затем ответьте на него самостоятельно. (Это активно поощряется на SO.) Andrie
@edgester: я могу переписать вопрос. Трудно было быть кратким. Проблема в том, что ggplot2 путает с датами / временем. Я хотел проиллюстрировать, сколько теоретических способов сделать это работает и проблемы с каждым из них. Hendy

Ваш Ответ

3   ответа
5

что ключевым моментом является то, что вам нужно сделать расчет частоты за пределами ggplot. Используйте aggregate () с geom_bar (stat = "identity"), чтобы получить гистограмму без переупорядоченных факторов. Вот пример кода:

require(ggplot2)

# scales goes with ggplot and adds the needed scale* functions
require(scales)

# need the month() function for the extra plot
require(lubridate)

# original data
#df<-read.csv("http://pastebin.com/download.php?i=sDzXKFxJ", header=TRUE)

# simulated data
years=sample(seq(2008,2012),681,replace=TRUE,prob=c(0.0176211453744493,0.302496328928047,0.323054331864905,0.237885462555066,0.118942731277533))
months=sample(seq(1,12),681,replace=TRUE)
my.dates=as.Date(paste(years,months,01,sep="-"))
df=data.frame(YM=strftime(my.dates, format="%Y-%b"),Date=my.dates,Year=years,Month=months)
# end simulated data creation

# sort the list just to make it pretty. It makes no difference in the final results
df=df[do.call(order, df[c("Date")]), ]

# add a dummy column for clarity in processing
df$Count=1

# compute the frequencies ourselves
freqs=aggregate(Count ~ Year + Month, data=df, FUN=length)

# rebuild the Date column so that ggplot works
freqs$Date=as.Date(paste(freqs$Year,freqs$Month,"01",sep="-"))

# I set the breaks for 2 months to reduce clutter
g<-ggplot(data=freqs,aes(x=Date,y=Count))+ geom_bar(stat="identity") + scale_x_date(labels=date_format("%Y-%b"),breaks="2 months") + theme_bw() + opts(axis.text.x = theme_text(angle=90))
print(g)

# don't overwrite the previous graph
dev.new()

# just for grins, here is a faceted view by year
# Add the Month.name factor to have things work. month() keeps the factor levels in order
freqs$Month.name=month(freqs$Date,label=TRUE, abbr=TRUE)
g2<-ggplot(data=freqs,aes(x=Month.name,y=Count))+ geom_bar(stat="identity") + facet_grid(Year~.) + theme_bw()
print(g2)
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit ExceededwhyError: User Rate Limit Exceeded Hendy
Error: User Rate Limit Exceededdf$CountError: User Rate Limit Exceededlubridate. Hendy
Error: User Rate Limit Exceeded%Y-%bError: User Rate Limit Exceeded%Y-%m-%dError: User Rate Limit Exceeded Hendy
0

основанный на подходе Гаудена». связано с параметром binwidth: ... + Geom_histogram (binwidth = 30, цвет = "белый") + ... Если мы изменим значение 30 на значение меньше 20, например 10, вы получите все частоты.

В статистике значения важнее, чем презентация, более важна простая графика для очень красивой картинки, но с ошибками.

Error: User Rate Limit Exceededwhy ggplot2Error: User Rate Limit Exceeded Hendy
Error: User Rate Limit Exceededgeom_histogram(binwidth = 10)Error: User Rate Limit Exceeded Hendy
30

UPDATE

Version 2: Using Date class

Я обновляю пример, чтобы продемонстрировать выравнивание надписей и установку пределов на графике. Я также демонстрирую, чтоas.Date действительно работает, когда используется последовательно (на самом деле это, вероятно, лучше подходит для ваших данных, чем мой предыдущий пример).

The Target Plot v2

date-based histogram

The Code v2

А вот (несколько чрезмерно) закомментированный код:

library("ggplot2")
library("scales")

dates <- read.csv("http://pastebin.com/raw.php?i=sDzXKFxJ", sep=",", header=T)
dates$Date <- as.Date(dates$Date)

# convert the Date to its numeric equivalent
# Note that Dates are stored as number of days internally,
# hence it is easy to convert back and forth mentally
dates$num <- as.numeric(dates$Date)

bin <- 60 # used for aggregating the data and aligning the labels

p <- ggplot(dates, aes(num, ..count..))
p <- p + geom_histogram(binwidth = bin, colour="white")

# The numeric data is treated as a date,
# breaks are set to an interval equal to the binwidth,
# and a set of labels is generated and adjusted in order to align with bars
p <- p + scale_x_date(breaks = seq(min(dates$num)-20, # change -20 term to taste
                                   max(dates$num), 
                                   bin),
                      labels = date_format("%Y-%b"),
                      limits = c(as.Date("2009-01-01"), 
                                 as.Date("2011-12-01")))

# from here, format at ease
p <- p + theme_bw() + xlab(NULL) + opts(axis.text.x  = theme_text(angle=45,
                                                                  hjust = 1,
                                                                  vjust = 1))
p
Version 1: Using POSIXct

Я пробую решение, которое делает все вggplot2рисование без агрегации и установка ограничений по оси х в период с начала 2009 года до конца 2011 года.

The Target Plot v1

plot with limits set in ggplot2

The Code v1
library("ggplot2")
library("scales")

dates <- read.csv("http://pastebin.com/raw.php?i=sDzXKFxJ", sep=",", header=T)
dates$Date <- as.POSIXct(dates$Date)

p <- ggplot(dates, aes(Date, ..count..)) + 
    geom_histogram() +
    theme_bw() + xlab(NULL) +
    scale_x_datetime(breaks = date_breaks("3 months"),
                     labels = date_format("%Y-%b"),
                     limits = c(as.POSIXct("2009-01-01"), 
                                as.POSIXct("2011-12-01")) )

p

Конечно, это может быть связано с игрой с опциями надписей на оси, но это завершает черчение чистой короткой процедурой в пакете для черчения.

Error: User Rate Limit Exceeded
Error: User Rate Limit Exceededmin(dates$num)Error: User Rate Limit Exceeded Hendy
Error: User Rate Limit Exceededc(as.Date(), as.Date())Error: User Rate Limit Exceeded Hendy
Error: User Rate Limit Exceededscale_x_dateError: User Rate Limit Exceeded Hendy
Error: User Rate Limit Exceeded

Похожие вопросы