【问题标题】:Multiple facet normalized bar graph with bar color differentiated by positive or negative value多面标准化条形图,条形颜色按正值或负值区分
【发布时间】:2019-04-11 07:13:58
【问题描述】:

我有一个像这样的数据框:

df<- data.frame(month= rep(c("Jan", "Feb", "Mar", "Apr", "May"), 3), 
       year= c(seq(2001:2003,5), rep(2002, 5), rep(2003, 5)), 
       clim_var= c(rep("precip_mm", 5), rep("tmin",5), rep("tmax", 5)), 
       anomaly= sample(-20:20, 15, replace = TRUE))
df<-df[-c(3,10),]
library("zoo")
df$date<- as.yearmon(paste(df$year, df$month), format= "%Y %b")

您会注意到有些日期可能会丢失,但大部分是各种气候变量的时间序列数据。我希望每个气候变量都是一个方面。 y 轴将为clim_var 列的每个级别绘制anomaly。这样我应该得到一个多因素的图,每个图都与此类似:

我试过这段代码(修改from

library(ggplot2)
gg<- ggplot(df, aes(x= seq_along(date), y = anomaly)) + 
geom_bar(stat = 'identity', aes(fill = anomaly>0), position = 'dodge', col = 
'transparent') + 
theme_bw() + scale_fill_discrete(guide = 'none') + 
labs(x = '', y = 'anomaly')
gg + facet_grid(clim_var~.)
gg+ scale_x_datetime(labels = date_format("%b %Y"))

问题似乎是在绘制日期。就好像它没有被识别为日期,所以每个clim_var 的数据占绘图区域的 1/3,x 轴是连续值而不是日期。我希望输出具有包含月份和年份的轴标签......

在我的真实数据集中有很多年的数据,所以最好只为一月指定标签,然后将其他月份作为不带标签的刻度线。对此的任何见解将不胜感激。

编辑:

更正的数据框使得每个clim-var 都有多年的数据

precip_mm<- data.frame(clim_var= rep("precip_mm",36),  month= rep(c("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sept", "Oct", "Nov", "Dec" ), 3), 
                   year= c(rep(2001,12),rep(2002,12), rep(2003, 12)), 
                   anomaly= sample(-20:20, 36, replace = TRUE))
tmin<- data.frame(clim_var= rep("tmin",36),  month= rep(c("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sept", "Oct", "Nov", "Dec" ), 3), 
                   year= c(rep(2001,12),rep(2002,12), rep(2003, 12)), 
                   anomaly= sample(-20:20, 36, replace = TRUE))
tmax<- data.frame(clim_var= rep("tmax",36),  month= rep(c("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sept", "Oct", "Nov", "Dec" ), 3), 
                   year= c(rep(2001,12),rep(2002,12), rep(2003, 12)), 
                   anomaly= sample(-20:20, 36, replace = TRUE))
df<- rbind(precip_mm, tmin)
df<-rbind(df, tmax)
df<-df[-c(3,10, 50, 100),]

library("zoo")
df$date<- as.yearmon(paste(df$year, df$month), format= "%Y %b")

cmets 中建议的调整

library(ggplot2)
gg<- ggplot(df, aes(x= date, y = anomaly)) + 
 geom_bar(stat = 'identity', aes(fill = anomaly>0), position = 'dodge', col = 
         'transparent') + 
theme_bw() + scale_fill_discrete(guide = 'none') + 
labs(x = '', y = 'anomaly')
gg + facet_grid(clim_var~.)
gg+ scale_x_yearmon()

输出不面向每个clim_var,但 x 轴已正确标记。

编辑2:

labels_month <- format(seq(from = min(df$date), to = 
max(df$date), by = "1 months"), "%Y-%b")
labels_month[rep(c(FALSE, TRUE), c(1, 11))] <- ""
labels_month<- as.Date(labels_month, format= "%Y-%b")

x_breaks <- seq(min(df$date), max(df$date), by = "1 months")

p1 <- ggplot(df, aes(x = factor(date), y = df)) +
geom_col(aes(fill = anomoly > 0),
       position = "dodge",
       col = "transparent") +
theme_bw(base_size = 12) + 
scale_fill_discrete(guide = "none") +
labs(x = "", y = "") + 
scale_x_date(expand = c(0.015, 0.015),
           labels = labels_month, 
           breaks = x_breaks) +
theme(axis.text.x = element_text(angle = 90, vjust = 0.5))
facet_grid(climvar ~ ., 
         labeller = label_parsed,
         switch = "y",
         scales = 'free_y') 
p1

【问题讨论】:

  • 我不确定我是否理解seq_along()。您是否想摆脱缺少日期的空格?如果是这样,您可以将yearmon 转换为绘图因子。如果没有,请使用 x = date 并使用 + scale_x_yearmon()(这是来自 zoo 的函数)。
  • 我已经编辑了我的帖子。阅读您的评论后,我意识到我发布的数据中有错误。除此之外,我已经尝试过您对新数据的建议,但没有得到多方面的输出。知道如何纠正吗?
  • 我认为您的错误是您确实在分面后将gg 分配给了一个对象,因此您将比例添加到原始图形而不是分面图形。你会想要,例如,gg + facet_grid(clim_var ~ .) + scale_x_yearmon()

标签: r ggplot2 plot


【解决方案1】:

这是你要找的吗?

library(zoo)
library(ggplot2)

set.seed(123)
precip_mm <- data.frame(
  clim_var = rep("precip_mm", 36),
  month = rep(c("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sept", "Oct", "Nov", "Dec"), 3),
  year = c(rep(2001, 12), rep(2002, 12), rep(2003, 12)),
  anomaly = sample(-20:20, 36, replace = TRUE))
tmin <- data.frame(
  clim_var = rep("tmin", 36),
  month = rep(c("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sept", "Oct", "Nov", "Dec"), 3),
  year = c(rep(2001, 12), rep(2002, 12), rep(2003, 12)),
  anomaly = sample(-20:20, 36, replace = TRUE))
tmax <- data.frame(
  clim_var = rep("tmax", 36),
  month = rep(c("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sept", "Oct", "Nov", "Dec"), 3),
  year = c(rep(2001, 12), rep(2002, 12), rep(2003, 12)),
  anomaly = sample(-20:20, 36, replace = TRUE))
df <- rbind(precip_mm, tmin)
df <- rbind(df, tmax)
df <- df[-c(3, 10, 50, 100), ]
df$date <- as.yearmon(paste(df$year, df$month), format = "%Y %b")


# Setup nice labels for T and P
df$clim_var <- factor(df$clim_var, 
                      levels = c("tmax", "tmin", "precip_mm"),
                      labels = c(expression("T"[max]~anomaly~(degree*C)),
                                 expression("T"[min]~anomaly~(degree*C)),
                                 expression("Precip anomaly ("*"mm)")))
# Plot
p1 <- ggplot(df, aes(x = factor(date), y = anomaly)) +
  geom_col(aes(fill = anomaly > 0),
           position = "dodge",
           col = "transparent") +
  theme_bw(base_size = 12) + 
  scale_fill_discrete(guide = "none") +
  labs(x = "", y = "") + 
  facet_grid(clim_var ~ ., 
             labeller = label_parsed,
             switch = "y",
             scales = 'free_y') +
  theme(strip.placement = 'outside',
        strip.background = element_blank(),
        axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1)) 
p1

如果要修改x轴,请查看answer

df$date2 <- as.Date(paste(df$year, df$month, "01", sep = "-"), format = "%Y-%b-%d")
p2 <- ggplot(df, aes(x = date2, y = anomaly)) +
  geom_col(aes(fill = anomaly > 0),
           position = "dodge",
           col = "transparent") +
  theme_bw(base_size = 12) + 
  scale_fill_discrete(guide = "none") +
  labs(x = "", y = "") + 
  facet_grid(clim_var ~ ., 
             labeller = label_parsed,
             switch = "y",
             scales = 'free_y') +
  theme(strip.placement = 'outside',
        strip.background = element_blank())  +
  scale_x_date(date_breaks = "12 months", date_labels = "%b-%Y")
p2

【讨论】:

  • 谢谢@Tung。我根据您的建议添加了一个编辑,但想知道您是否可以帮我弄清楚为什么我不能每 12 个月为轴编号。
【解决方案2】:

如果你有大量的方面,你可能会更好facet_wrap,它可以像这样解决你的规模问题:

gg<- ggplot(df, aes(x= seq_along(date), y = anomaly)) + 
  geom_bar(stat = 'identity', aes(fill = anomaly>0), position = 'dodge', col = 
             'transparent') + 
  theme_bw() + scale_fill_discrete(guide = 'none') + 
  labs(x = '', y = 'anomaly')
gg + facet_wrap(clim_var~., scales= "free_x")

您可以随意使用facet_wrapnrowncol塑造它。

所以使用日期格式:

df$date<- as.Date(paste(df$year, df$month, "1", sep="-"), format="%Y-%b-%d")

library(ggplot2)
library(scales)
gg<- ggplot(df, aes(x= date, y = anomaly)) + 
  geom_bar(stat = 'identity', aes(fill = anomaly>0), position = 'dodge', col = 
             'transparent') + 
  theme_bw() + scale_fill_discrete(guide = 'none') + 
  labs(x = '', y = 'anomaly')
gg + facet_wrap(clim_var~., scales= "free")+ scale_x_date(breaks = date_breaks("2 months"),labels = date_format("%m/%y"))

我更喜欢这种方法,因为它为我的日期轴提供了很大的灵活性。

【讨论】:

  • 请注意,降水和温度的单位不同,所以这个图没有多大意义
  • @Tung 你是对的。应该使用free 选项而不是free_x。我只是在修复被问到的 shared 规模问题。
  • 这是正确的,它们是不同的单位。此外,对于长期数据,我更喜欢水平面进行比较。更适合用于超过 20 年数据的出版物和幻灯片。
  • @Danielle 我无法对您的帖子发表评论,因为我的声誉低于 50,但您忘记为 facet_wrap 添加 scales= "free" 选项
猜你喜欢
  • 2014-10-22
  • 2021-11-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-08
  • 2020-05-16
  • 1970-01-01
相关资源
最近更新 更多