8

我开始在 Excel 中制作日历,但认为用 R 代替它可能很容易。(注意:我知道各种热图日历包,但我更喜欢使用ggplot2。)最终我想制作一个显示从给定日期开始的 12 个月的日历,每个月作为一个小框显示 4 或 5 周y 轴(第 1 周在顶部,第 4 周或第 5 周在底部)和沿 x 轴的一周中的天数(从星期一开始)。

我认为这将是一个 15 分钟的工作(创建所有月份的数据,使用reshape然后使用格式化一点facet_wrap)但几乎立即遇到了问题,如下图所示 - 虽然月份的日子不按顺序排列,但这周似乎还可以。在 R 中排序数据是我的克星;我真的应该解决这个问题。无论如何,下面的图片显示了我到目前为止所拥有的,代码在下面。这只是一个有趣的项目,并不紧急,但欢迎任何帮助和/或修饰。

日历

require(ggplot2)
require(scales)
require(lubridate)

date.start <- as.Date('2013-09-01')
date.end <- date.start + months(1)

mydf <- data.frame(mydate = seq(as.Date(date.start),
                       as.Date(date.end) - days(1),
                       by = 'day'))

mydf$month <- month(mydf$mydate)
mydf$week <- week(mydf$mydate)
mydf$day <- day(mydf$mydate)
mydf$dow <- as.factor(format(mydf$mydate, format = "%a"))
levels(mydf$dow) <- c('Mon','Tue','Wed','Thu','Fri','Sat','Sun')

ggplot(mydf, aes(x = dow, y = as.factor(week))) +
    geom_tile(colour = "black", fill = "white", label = mydf$day) +
    geom_text(label = mydf$day, size = 4, colour = "black") +
    scale_x_discrete(expand = c(0,0)) +
    theme(axis.ticks = element_blank()) +
    theme(axis.title.y = element_blank()) +
    theme(axis.title.x = element_blank()) +
    theme(panel.background = element_rect(fill = "transparent"))+
    theme(legend.position = "none") +
    theme()
4

3 回答 3

6

这行代码是错误的:

levels(mydf$dow) <- c('Mon','Tue','Wed','Thu','Fri','Sat','Sun')

这是因为mydf$dow它已经是一个因素,并且通过使用levels您只是重命名当前级别。在这种情况下,您只是重命名"Fri" "Mon" "Sat" "Sun" "Thu" "Tue" "Wed"'Mon','Tue','Wed','Thu','Fri','Sat','Sun',这将在最后造成混乱。

如果您查看mydf示例,您将看到:

       mydate month week day dow
1  2013-09-01     9   35   1 Thu
2  2013-09-02     9   36   2 Tue
3  2013-09-03     9   36   3 Sat
4  2013-09-04     9   36   4 Sun
5  2013-09-05     9   36   5 Fri
6  2013-09-06     9   36   6 Mon
7  2013-09-07     9   36   7 Wed

由于重命名,日期名称不再与日期匹配。

更正后,一切都按预期工作:

require(ggplot2)
require(scales)
require(lubridate)


date.start <- as.Date('2013-09-01')
date.end <- date.start + months(1)

mydf <- data.frame(mydate = seq(as.Date(date.start),
                                as.Date(date.end) - days(1),
                                by = 'day'))

mydf$month <- month(mydf$mydate)
mydf$week <- week(mydf$mydate)
mydf$day <- day(mydf$mydate)
mydf$dow <- as.factor(format(mydf$mydate, format = "%a"))

mydf$dow <- factor(mydf$dow, levels=c('Mon','Tue','Wed','Thu','Fri','Sat','Sun'))

ggplot(mydf, aes(x = dow, y = as.factor(week))) +
  geom_tile(colour = "black", fill = "white", label = mydf$day) +
  geom_text(label = mydf$day, size = 4, colour = "black") +
  scale_x_discrete(expand = c(0,0)) +
  theme(axis.ticks = element_blank()) +
  theme(axis.title.y = element_blank()) +
  theme(axis.title.x = element_blank()) +
  theme(panel.background = element_rect(fill = "transparent"))+
  theme(legend.position = "none") +
  theme()

在此处输入图像描述

于 2013-09-11T13:42:18.153 回答
6

week.f以相反的顺序创建具有级别的列。我们已经使用"%U"(假设美国惯例,但如果您希望使用英国惯例"%W"并更改因子水平的顺序dow)。此外,我们允许任意日期输入计算月初,并ggplot稍微简化了调用。

library(ggplot2)

input <- as.Date("2013-09-11") # input date

st <- as.Date(cut(input, "month")) # calculate start of month
dates31 <- st + 0:30 # st and next 30 dates (31 in all)
dates <- dates31[months(dates31) == months(st)] # keep only dates in st's month

week.ch <- format(dates, "%U") # week numbers

mydf <- data.frame(
   day = as.numeric(format(dates, "%d")),
   week.f = factor(week.ch, rev(unique(week.ch))),
   dow = factor(format(dates, "%a"), c("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"))
)

ggplot(mydf, aes(x = dow, y = week.f)) +
    geom_tile(colour = "black", fill = "white") +
    geom_text(label = mydf$day, size = 4) + 
    scale_x_discrete(expand = c(0,0)) +
    theme(axis.ticks = element_blank()) +
    theme(axis.title = element_blank()) +
    theme(panel.background = element_rect(fill = "transparent"))+
    theme(legend.position = "none")

在此处输入图像描述

顺便说一句,calTeachingDemos 包中有一个功能,可以使用经典图形构建一个月日历。

于 2013-09-11T13:34:43.530 回答
4

干得好:

start <- as.Date("2013-09-1")
numdays <- 30

weeknum <- function(date){
  z <- as.Date(date, format="%Y-%m-%d")
  as.numeric( format(z-1, "%U"))
}


dates <- data.frame(date=seq(start, length.out=numdays, by="1 day"))
dates <- within(dates, {
  weeknum <- weeknum(date)
  month   <- format(date, "%m")
  weekday <- format(date, "%a")
  day     <- format(date, "%d")
})

dates$weekday <- factor(dates$weekday, levels=c("Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"))

library(ggplot2)
ggplot(dates, aes(x=weekday, y=weeknum)) + 
  geom_tile(fill="blue", col="white") +
  geom_text(aes(label=day)) 

在此处输入图像描述

于 2013-09-11T13:39:00.487 回答