1. 南丁格尔玫瑰图的前世今生
第一次看到南丁格尔玫瑰图时,我被它独特的美感震撼到了。这种图表看起来像一朵绽放的玫瑰,但实际上它是柱状图在极坐标系下的变形。这种图表最早由弗洛伦斯·南丁格尔在克里米亚战争期间使用,用来直观展示士兵伤亡数据。你可能不知道,正是这张图说服了当时的英国政府改善战地医院条件,拯救了无数生命。
在实际工作中,我发现这种图表特别适合展示周期性数据或多维度的对比。比如我们公司上季度做区域销售分析时,用传统柱状图展示10个区域的销售额和利润率,决策者看了直摇头。但改用玫瑰图后,CEO一眼就看出哪个区域表现最好,哪个需要重点关注。这就是可视化魔力的最好证明。
与传统柱状图相比,玫瑰图有三个明显优势:一是空间利用率高,在有限面积内展示更多信息;二是视觉冲击力强,容易吸引注意力;三是适合展示周期性数据,比如月度、季度报表。不过要注意,由于面积是半径的平方关系,玫瑰图会放大数值差异,这点在使用时需要特别注意。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 数据准备与预处理
2.1 数据获取与清洗
我常用TidyTuesday项目的数据做演示,这次我们使用远足路线数据。首先加载必要的包并导入数据:
r复制library(ggplot2)
library(dplyr)
library(stringr)
hike_data <- readr::read_rds("https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2020/2020-11-24/hike_data.rds")
原始数据需要做一些清洗。比如location字段包含"区域 -- 具体地点"的信息,我们只需要提取区域部分:
r复制hike_data$region <- as.factor(word(hike_data$location, 1, sep = " -- "))
长度字段是字符型,包含单位和数值,需要转换为纯数字:
r复制hike_data$length_num <- as.numeric(sapply(strsplit(hike_data$length, " "), "[[", 1))
2.2 数据聚合与计算
商业报告中通常需要聚合数据。比如我们要展示每个区域路线总长度和平均海拔增益:
r复制plot_df <- hike_data %>%
group_by(region) %>%
summarise(
sum_length = sum(length_num),
mean_gain = mean(as.numeric(gain)),
n = n()
) %>%
mutate(mean_gain = round(mean_gain, digits = 0))
这里我特意保留了路线数量(n),后面可以用颜色映射这个变量,实现一个图表展示三个维度的数据。这是商业报告最爱的技巧——用最少空间传递最多信息。
3. 基础玫瑰图绘制
3.1 从柱状图到极坐标
玫瑰图的本质是极坐标下的柱状图。我们先画普通柱状图:
r复制p <- ggplot(plot_df) +
geom_col(
aes(
x = reorder(str_wrap(region, 5), sum_length),
y = sum_length,
fill = n
),
position = "dodge2",
show.legend = TRUE,
alpha = .9
)
关键步骤是转换为极坐标:
r复制p <- p + coord_polar()
这时候图表已经初具雏形,但有几个问题:区域标签重叠、刻度线不清晰、颜色映射不明显。别急,我们一步步优化。
3.2 添加参考线与刻度
为了让图表更易读,我习惯添加参考线和刻度:
r复制p +
geom_hline(
aes(yintercept = y),
data.frame(y = c(0:3) * 1000),
color = "lightgrey"
) +
geom_segment(
aes(
x = reorder(str_wrap(region, 5), sum_length),
y = 0,
xend = reorder(str_wrap(region, 5), sum_length),
yend = 3000
),
linetype = "dashed",
color = "gray12"
)
这里用geom_hline添加水平参考线,geom_segment添加径向的虚线。注意yend=3000要略大于数据最大值,保证虚线贯穿整个图表。
4. 商业级美化技巧
4.1 颜色与图例优化
商业图表对颜色要求很高。我推荐使用scale_fill_gradientn实现平滑渐变:
r复制scale_fill_gradientn(
"路线数量",
colours = c("#6C5B7B","#C06C84","#F67280","#F8B195")
) +
guides(
fill = guide_colorsteps(
barwidth = 15,
barheight = .5,
title.position = "top",
title.hjust = .5
)
)
这里有几个细节:1) 使用有美感的紫色到橙色渐变;2) guide_colorsteps让图例显示为平滑色阶;3) 调整图例大小和标题位置。
4.2 主题与文字调整
最后是主题微调,这是让图表脱颖而出的关键:
r复制theme_minimal() +
theme(
axis.title = element_blank(),
axis.ticks = element_blank(),
axis.text.y = element_blank(),
axis.text.x = element_text(color = "gray12", size = 12),
legend.position = "bottom"
)
我移除了所有不必要的元素(坐标轴标题、刻度线),只保留区域标签。将图例放在底部,文字使用深灰色而非纯黑,整体看起来更专业。
5. 进阶技巧与避坑指南
5.1 多维度数据展示
在实际项目中,我经常需要在玫瑰图中展示更多信息。比如可以在每个扇形顶端添加点,表示平均海拔:
r复制geom_point(
aes(
x = reorder(str_wrap(region, 5), sum_length),
y = mean_gain
),
size = 3,
color = "darkblue"
)
这样一张图就同时展示了总长度、路线数量和平均海拔三个维度。但要注意不要过度设计,超过三个维度会让图表难以理解。
5.2 常见问题解决
在制作玫瑰图时,我踩过不少坑。最常见的问题是标签重叠,解决方法有:
- 使用str_wrap自动换行:
r复制x = reorder(str_wrap(region, 5), sum_length)
- 调整标签大小和边距:
r复制theme(axis.text.x = element_text(size = 10, margin = margin(t = 10)))
另一个问题是极坐标下的比例失真。由于面积与半径平方成正比,数值差异会被放大。解决方法是在数据预处理阶段进行对数变换,或者添加明确的刻度线提示观众。
6. 完整代码与实战案例
下面是我在一个零售分析项目中的完整应用案例。我们需要比较12个月的产品销量和利润率:
r复制# 数据准备
sales_data <- read.csv("monthly_sales.csv") %>%
mutate(
month = factor(month.abb[month], levels = month.abb),
profit_ratio = profit / revenue
)
# 绘图
ggplot(sales_data) +
geom_col(
aes(
x = month,
y = revenue,
fill = profit_ratio
),
width = 0.9,
alpha = 0.8
) +
geom_hline(
aes(yintercept = y),
data.frame(y = seq(0, 1e6, by = 2e5)),
color = "lightgrey"
) +
coord_polar() +
scale_fill_gradientn(
"利润率",
colours = c("#2c7bb6", "#abd9e9", "#ffffbf", "#fdae61", "#d7191c"),
values = scales::rescale(c(0, 0.1, 0.2, 0.3, 0.4))
) +
theme_minimal() +
theme(
axis.text.y = element_blank(),
axis.title = element_blank(),
panel.grid.major.x = element_blank()
)
这个图表成功帮助管理层发现,虽然12月销量最高,但利润率却低于平均水平,促使他们重新审视年底促销策略。这就是数据可视化的力量——让洞见一目了然。
