R 更改ggplot2条形图中条形图的形状

R 更改ggplot2条形图中条形图的形状,r,ggplot2,R,Ggplot2,我有一些关于中国风能生产的数据。我将数据可视化为一个(圆形)条形图,最终目的是让它看起来像一个风车(是的,我知道这不是很好的“数据分析”,只是一点乐趣)。我如何才能将棒的形状从方形改为更像涡轮机上的叶片(理想情况下,只是通过改变棒的形状,尽管我猜使用grob可能是可行的) 圆形条形图的代码和数据: data\u clean创建一个看起来像您想要的形状(例如风车叶片)的SVG路径,然后使用geom\u polygon在图形上任意位置绘制它。不久前我在我的博客上创建了一个教程:这里有一个替代@ssp

我有一些关于中国风能生产的数据。我将数据可视化为一个(圆形)条形图,最终目的是让它看起来像一个风车(是的,我知道这不是很好的“数据分析”,只是一点乐趣)。我如何才能将棒的形状从方形改为更像涡轮机上的叶片(理想情况下,只是通过改变棒的形状,尽管我猜使用grob可能是可行的) 圆形条形图的代码和数据:


data\u clean创建一个看起来像您想要的形状(例如风车叶片)的SVG路径,然后使用
geom\u polygon
在图形上任意位置绘制它。不久前我在我的博客上创建了一个教程:

这里有一个替代@ssp3nc3r的答案。免责声明:请原谅我完全无法充分绘制涡轮叶片。希望您能理解这个想法,但就像@ssp3nc3r的答案一样,您需要首先定义刀片。这是一个由7个点定义的刀片:

raw_blade <- data.frame(x=c(0.1,0.9,1,1,0.5,0,0),
                    y=c(0,0,4.5,8,10,8,4.5))

ggplot(raw_blade, aes(x,y)) + geom_polygon() + xlim(-4,4)

看起来非常合适!以下是极坐标版本:

p + coord_polar()

我太喜欢这个了。这里有一个基于geom多边形的快速geom_风车。其思想是使用一个自定义的Stat,它基于

库(ggplot2)
图书馆(网格)
ggplot(数据清洁,aes(x=年份,y=值,颜色=id,组=id))+
geom_风车(颜色=黑色),aes(填充=值_TWh))


ggplot(数据清洁,aes(x=年份,y=值,颜色=id,组=id))+
geom_风车(颜色=黑色),aes(填充=值_TWh))+
coord_polar()


ggplot(数据清洁,aes(x=年份,y=值,颜色=id,组=id))+
geom_风车(颜色=黑色),aes(填充=值),span_x=2)


ggplot(数据清洁,aes(x=年份,y=值,颜色=id,组=id))+
geom_风车(颜色=黑色),aes(填充=值),span_x=2)+
coord_polar()

geom_风车和stat_风车

stat_windmill <- function(mapping = NULL, data = NULL, geom = "polygon",
                          position = "identity", na.rm = FALSE, show.legend = NA, 
                          inherit.aes = TRUE, span_x = 1, ...) {
  layer(
    stat = StatWindmill, data = data, mapping = mapping, geom = geom, 
    position = position, show.legend = show.legend, inherit.aes = inherit.aes,
    params = list(na.rm = na.rm, span_x = span_x, ...)
  )
}

StatWindmill <- ggproto("StatWindmill", Stat,
                     compute_group = function(data, scales, span_x = 1) {
                       blade_frame <- data.frame(
                         x_map=c(0.15,0.85,0.95,0.95,0.5,0.05,0.05),
                         y = c(0,0,0.45,0.8,1,0.8,0.45)
                       )
                       new_x <- (data$x - span_x/2) + (span_x * blade_frame$x_map)
                       new_y <- data$y * blade_frame$y
                       new_blade <- data.frame(x=new_x, y=new_y)
                       new_blade
                      
                     },
                     
                     required_aes = c("x", "y")
)

geom_windmill <- function(mapping = NULL, data = NULL,
                         stat = "identity", position = "identity",
                         rule = "evenodd",
                         ...,
                         na.rm = FALSE,
                         show.legend = NA,
                         inherit.aes = TRUE) {
  layer(
    data = data,
    mapping = mapping,
    stat = StatWindmill,
    geom = GeomPolygon,
    position = position,
    show.legend = show.legend,
    inherit.aes = inherit.aes,
    params = list(
      na.rm = na.rm,
      rule = rule,
      ...
    )
  )
}



stat_windmill我不确定这是否可以做到,如果可以的话会很有趣。无论如何,在我看来,你的情节已经相当像风车了!谢谢你的详细和令人印象深刻的回答!因此,当我尝试运行行
my_blades@alex_stephenson时,这是for循环中的一个小错误,您需要将
group=rep(I,nrow(blade))
替换为
group=rep(I,nrow(blade_frame))
@chemdork干得好!看看我的数据-你会发现你基本上已经完成了工作!在添加分组变量后,Stat中的compute_group将为您进行分组,而不是创建这个复杂的for循环。你可以看到,已经没有for循环了!扩展统计数据实际上使做这类事情更加容易,分组也是ggplot最大的优点。啊,是的,我注意到了这个问题<代码>刀片
就是@Tjebo提到的
刀片框架
:-o我将进行编辑。@Tjebo-回答得很好,我喜欢将此作为自定义统计的想法(老实说,我不知道你能这么容易做到)。非常有用,即使您的目标不是创建风车:)惊人:我必须学习如何制作一些像这样的自定义统计数据,并使用
ggproto
对象。你让我的答案更清晰了。也许有人可以添加一个更好看的风车叶片,我们将有一个很好的团队努力。:)@chemdork123是一个非常(!)好的小插曲。一开始可能会让人望而生畏,但正如你所看到的,它实际上可以让事情变得更容易!当你需要创建你自己的grob绘图函数时,它会变得有点疯狂(我还不在那里)
p + coord_polar()
stat_windmill <- function(mapping = NULL, data = NULL, geom = "polygon",
                          position = "identity", na.rm = FALSE, show.legend = NA, 
                          inherit.aes = TRUE, span_x = 1, ...) {
  layer(
    stat = StatWindmill, data = data, mapping = mapping, geom = geom, 
    position = position, show.legend = show.legend, inherit.aes = inherit.aes,
    params = list(na.rm = na.rm, span_x = span_x, ...)
  )
}

StatWindmill <- ggproto("StatWindmill", Stat,
                     compute_group = function(data, scales, span_x = 1) {
                       blade_frame <- data.frame(
                         x_map=c(0.15,0.85,0.95,0.95,0.5,0.05,0.05),
                         y = c(0,0,0.45,0.8,1,0.8,0.45)
                       )
                       new_x <- (data$x - span_x/2) + (span_x * blade_frame$x_map)
                       new_y <- data$y * blade_frame$y
                       new_blade <- data.frame(x=new_x, y=new_y)
                       new_blade
                      
                     },
                     
                     required_aes = c("x", "y")
)

geom_windmill <- function(mapping = NULL, data = NULL,
                         stat = "identity", position = "identity",
                         rule = "evenodd",
                         ...,
                         na.rm = FALSE,
                         show.legend = NA,
                         inherit.aes = TRUE) {
  layer(
    data = data,
    mapping = mapping,
    stat = StatWindmill,
    geom = GeomPolygon,
    position = position,
    show.legend = show.legend,
    inherit.aes = inherit.aes,
    params = list(
      na.rm = na.rm,
      rule = rule,
      ...
    )
  )
}


data_clean <- structure(list(Type = c("Wind", "Wind", "Wind", "Wind", "Wind", 
                                      "Wind", "Wind", "Wind", "Wind", "Wind"), Year = c(2010, 2011, 
                                                                                        2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019), Value_TWh = c(49.4, 
                                                                                                                                                       74.1, 103, 138.3, 159.8, 185.6, 240.9, 303.4, 366, 405.7), id = 1:10, 
                             film_year = c("Year: 2010 . Energy Output: 49.4", "Year: 2011 . Energy Output: 74.1", 
                                           "Year: 2012 . Energy Output: 103", "Year: 2013 . Energy Output: 138.3", 
                                           "Year: 2014 . Energy Output: 159.8", "Year: 2015 . Energy Output: 185.6", 
                                           "Year: 2016 . Energy Output: 240.9", "Year: 2017 . Energy Output: 303.4", 
                                           "Year: 2018 . Energy Output: 366", "Year: 2019 . Energy Output: 405.7"
                             )), class = c("spec_tbl_df", "tbl_df", "tbl", "data.frame"
                             ), row.names = c(NA, -10L))