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