如何用R将婴儿24小时睡眠喂养数据可视化为时钟式饼图或条形图
婴儿睡眠与喂养时段可视化方案
需求说明
出于研究需求,需追踪婴儿24小时内的睡眠与喂养时段,实现以下可视化效果:
- 极坐标时钟图(环形饼图):绿色代表喂养时段,蓝色代表睡眠时段,时段间用白色间隙分隔
- 水平条形图(时间轴样式)
- 欢迎其他可视化思路补充
已通过lubridate包完成数据预处理,将时间转换为datetime格式并拆分跨午夜的时段,预处理代码如下:
library(tidyverse) library(lubridate) df <- data.frame( date = c("2025-08-30", "2025-08-30", "2025-08-30", "2025-08-30", "2025-08-30", "2025-08-30", "2025-08-30", "2025-08-30", "2025-08-30"), activity = c("sleep", "feed", "sleep", "feed", "sleep", "feed", "sleep", "feed", "sleep"), start_time = c("1:00 AM", "2:30 AM", "3:00 AM", "6:15 AM", "8:00 AM", "11:00 AM", "1:20 PM", "6:00 PM", "8:00 PM"), end_time = c("2:30 AM", "2:40 AM", "6:00 AM", "6:30 AM", "9:30 AM", "11:24 AM", "3:40 PM", "7:00 PM", "2:00 AM") ) # 标记跨午夜时段 df = df %>% mutate(midnight_flag = if_else( str_detect(start_time, "PM") & str_detect(end_time, "AM"), TRUE, FALSE), start_time = str_c(date, " ", start_time) %>% ymd_hm(), end_time = str_c(date, " ", end_time) %>% ymd_hm()) %>% mutate(end_time = if_else( midnight_flag == TRUE, end_time + days(1), end_time )) # 拆分跨午夜的时段为两行 df = df %>% split(seq_len(nrow(.))) %>% map_dfr(function(row) { if (row$midnight_flag) { midnight <- ceiling_date(row$start_time, unit = "day") tibble( activity = row$activity, date = c(as_date(row$start_time), as_date(midnight)), start_time = c(row$start_time, midnight), end_time = c(midnight, row$end_time) ) } else { tibble( activity = row$activity, date = as_date(row$start_time), start_time = row$start_time, end_time = row$end_time)}})
可视化实现
1. 极坐标时钟图(24小时环形)
该方案模拟24小时时钟样式,用环形区块展示不同时段的活动,通过白色间隙区分相邻活动。
数据准备
先将时间转换为一天内的小时数,添加间隙占位行:
# 转换为一天内的小时数,计算时长 df_plot <- df %>% mutate( start_hour = hour(start_time) + minute(start_time)/60, end_hour = hour(end_time) + minute(end_time)/60, duration = end_hour - start_hour ) %>% # 筛选目标日期(示例为2025-08-30) filter(date == ymd("2025-08-30")) # 添加时段间隙:每个活动结束后加0.1小时的空白(可根据需求调整宽度) gap_rows <- df_plot %>% mutate( activity = "gap", start_hour = end_hour, end_hour = end_hour + 0.1, duration = 0.1 ) %>% # 确保间隙不超过24小时边界 mutate(end_hour = ifelse(end_hour > 24, 24, end_hour), duration = end_hour - start_hour) # 合并活动与间隙数据,按时间排序 df_with_gaps <- bind_rows(df_plot, gap_rows) %>% arrange(start_hour) %>% filter(start_hour < 24)
绘图代码
# 定义颜色映射:蓝色睡眠、绿色喂养、白色间隙 color_map <- c("sleep" = "#4a90e2", "feed" = "#50c878", "gap" = "white") ggplot(df_with_gaps, aes(xmin = 0, xmax = 1, ymin = start_hour, ymax = end_hour, fill = activity)) + geom_rect(color = "white", size = 0.5) + # 白色边框强化间隙效果 coord_polar(theta = "y", start = -pi/2) + # 极坐标布局,0点(午夜)位于顶部 scale_y_continuous( breaks = seq(0,24,3), labels = c("00:00", "03:00", "06:00", "09:00", "12:00", "15:00", "18:00", "21:00", "24:00") ) + scale_fill_manual(values = color_map) + theme_minimal() + theme( axis.title = element_blank(), panel.grid = element_blank(), axis.text.y = element_text(size = 10), legend.position = "bottom", legend.title = element_blank() ) + labs(title = "婴儿24小时睡眠与喂养时段")
2. 水平条形图(时间轴样式)
该方案用横向条形直观展示一天内的活动时段,适合快速查看时间分布。
ggplot(df_plot, aes(xmin = start_hour, xmax = end_hour, ymin = 0.8, ymax = 1.2, fill = activity)) + geom_rect(color = "white", size = 1) + # 白色边框区分相邻活动 scale_x_continuous( breaks = seq(0,24,2), labels = paste0(seq(0,24,2), ":00"), limits = c(0,24) ) + scale_fill_manual(values = c("sleep" = "#4a90e2", "feed" = "#50c878")) + theme_minimal() + theme( axis.title.x = element_text(label = "时间"), axis.title.y = element_blank(), axis.text.y = element_blank(), panel.grid.y = element_blank(), legend.position = "bottom", legend.title = element_blank(), axis.ticks.y = element_blank() ) + labs(title = "婴儿24小时睡眠与喂养时段")
3. 其他可视化思路
热力图(时段密集度展示)
将一天划分为15分钟的时间块,用颜色标记每个块的活动类型,直观展示时段分布:
# 生成15分钟间隔的时间网格 time_grid <- tibble( time = seq(ymd_hm("2025-08-30 00:00"), ymd_hm("2025-08-30 23:45"), by = "15 mins"), hour_block = hour(time) + minute(time)/60 ) # 匹配每个时间块对应的活动 time_grid <- time_grid %>% left_join(df_plot, by = character()) %>% filter(hour_block >= start_hour & hour_block < end_hour) %>% select(time, activity) %>% distinct(time, .keep_all = TRUE) # 绘制热力图 ggplot(time_grid, aes(x = hour(time) + minute(time)/60, y = 1, fill = activity)) + geom_tile(width = 0.25, height = 1) + # 15分钟对应0.25小时宽度 scale_x_continuous( breaks = seq(0,24,2), labels = paste0(seq(0,24,2), ":00"), limits = c(0,24) ) + scale_fill_manual(values = c("sleep" = "#4a90e2", "feed" = "#50c878")) + theme_minimal() + theme( axis.title.x = element_text(label = "时间"), axis.title.y = element_blank(), axis.text.y = element_blank(), panel.grid = element_blank(), legend.position = "bottom", legend.title = element_blank() ) + labs(title = "婴儿24小时睡眠与喂养热力图(15分钟间隔)")
交互式可视化(plotly)
将极坐标图或条形图转为交互式,支持鼠标悬停查看具体时段信息:
library(plotly) # 基于极坐标图生成交互式版本 p <- ggplot(df_with_gaps, aes(xmin = 0, xmax = 1, ymin = start_hour, ymax = end_hour, fill = activity, text = paste0(activity, "\n开始时间: ", format(start_time, "%H:%M"), "\n结束时间: ", format(end_time, "%H:%M")))) + geom_rect(color = "white", size = 0.5) + coord_polar(theta = "y", start = -pi/2) + scale_y_continuous(breaks = seq(0,24,3), labels = c("00:00", "03:00", "06:00", "09:00", "12:00", "15:00", "18:00", "21:00", "24:00")) + scale_fill_manual(values = color_map) + theme_minimal() + theme(axis.title = element_blank(), panel.grid = element_blank(), axis.text.y = element_text(size = 10), legend.position = "bottom", legend.title = element_blank()) + labs(title = "婴儿24小时睡眠与喂养时段") # 转为交互式图表 ggplotly(p, tooltip = "text")
内容的提问来源于stack exchange,提问作者user3710004
相关产品推荐
相关产品推荐

