如何生成24小时时间线事件分布图谱:颜色深浅对应事件间隔
问题描述
我有一个包含两列的活动数据集:
$ respondent_id : chr [1:20836241] "1086624" "1086624" "1086624" "1086624" ... $ fulldate: POSIXct[1:20836241], format: "2023-05-25 05:45:40" "2023-05-22 19:42:44" ...
需要生成24小时时间线活动分布图谱,用颜色深浅表示事件间隔(间隔越短颜色越深)。尝试用Python实现时出现维度不匹配报错,代码及错误信息如下:
报错代码
import matplotlib.pyplot as plt from matplotlib.dates import DayLocator, HourLocator, date2num, num2date import datetime # Import the datetime module # Sample data (replace with your actual call log data) call_times = [ "2023-11-19 08:00:00", "2023-11-19 08:10:00", "2023-11-19 08:30:00", "2023-11-19 09:00:00", "2023-11-20 10:00:00", "2023-11-20 11:00:00", ] # Convert call times into date objects dates = [datetime.datetime.strptime(t, "%Y-%m-%d %H:%M:%S") for t in call_times] # Calculate the time difference between consecutive calls time_deltas = [abs(dates[i] - dates[i-1]).total_seconds() for i in range(1, len(dates))] # Assign darkness values based on time difference (heuristic) darkness = [min(td / 3600, 1) for td in time_deltas] # Normalize to 0-1 # Plot the data with darkness representing call frequency plt.figure(figsize=(10, 6)) days = date2num(dates) plt.plot(days, darkness, marker='o', linestyle='-') # Format the x-axis for day and hour labels plt.gca().xaxis.set_major_locator(DayLocator()) plt.gca().xaxis.set_major_formatter(DateFormatter("%d")) plt.gca().xaxis.set_minor_locator(HourLocator(span=24)) plt.gca().xaxis.set_minor_formatter(DateFormatter("%H")) # Set labels and title plt.xlabel("Date & Time") plt.ylabel("Call Frequency (Darker = More Frequent)") plt.title("Outgoing Mobile Call Sequence") # Rotate x-axis labels for readability plt.xticks(rotation=45) plt.grid(True) plt.tight_layout() plt.show()
报错信息
Traceback (most recent call last): File "/home/doreena/venvs/dd/lib/python3.10/site-packages/IPython/core/interactiveshell.py", line 3553, in run_code exec(code_obj, self.user_global_ns, self.user_ns) File "<ipython-input-3-107fc1c9c959>", line 27, in <module> plt.plot(days, darkness, marker='o', linestyle='-') File "/home/doreena/venvs/dd/lib/python3.10/site-packages/matplotlib/pyplot.py", line 3590, in plot return gca().plot( File "/home/doreena/venvs/dd/lib/python3.10/site-packages/matplotlib/axes/_axes.py", line 1724, in plot lines = [*self._get_lines(self, *args, data=data, **kwargs)] File "/home/doreena/venvs/dd/lib/python3.10/site-packages/matplotlib/axes/_base.py", line 303, in __call__ yield from self._plot_args( File "/home/doreena/venvs/dd/lib/python3.10/site-packages/matplotlib/axes/_base.py", line 499, in _plot_args raise ValueError(f"x and y must have same first dimension, but " ValueError: x and y must have same first dimension, but have shapes (6,) and (5,)
解决方案
1. 报错核心原因及修复逻辑
报错源于维度不匹配:dates有6个时间点,darkness是相邻时间点的间隔计算结果,仅5个值,无法直接对应绘制。
合理修复思路:将间隔值绑定到两个事件的中间时刻,或者给第一个事件补默认间隔值。这里采用中间时刻方案,因为间隔是两个事件之间的属性,对应中间位置更符合逻辑。
2. 完整Python实现代码
import matplotlib.pyplot as plt from matplotlib.dates import DayLocator, HourLocator, date2num, DateFormatter import datetime import numpy as np # 替换为你的实际数据 call_times = [ "2023-11-19 08:00:00", "2023-11-19 08:10:00", "2023-11-19 08:30:00", "2023-11-19 09:00:00", "2023-11-20 10:00:00", "2023-11-20 11:00:00", ] # 转换为datetime对象并确保时间有序 dates = sorted([datetime.datetime.strptime(t, "%Y-%m-%d %H:%M:%S") for t in call_times]) dates_num = date2num(dates) # 计算相邻事件的时间间隔(秒):date2num返回天,转成秒 time_deltas = np.diff(dates_num) * 86400 # 计算间隔对应的中间时刻(x轴位置) mid_times = (dates_num[:-1] + dates_num[1:]) / 2 # 归一化间隔值:间隔越短,颜色越深(用1-归一化值实现深色对应短间隔) norm_deltas = time_deltas / time_deltas.max() darkness = 1 - norm_deltas # 范围0-1,0最浅,1最深 # 绘制图形 plt.figure(figsize=(12, 6)) # 标记每个事件的时间点 plt.scatter(dates_num, [0.5]*len(dates_num), color='gray', alpha=0.7, label='Event') # 绘制间隔线段,用灰度深浅表示间隔长度 for i in range(len(mid_times)): plt.plot([dates_num[i], dates_num[i+1]], [0.5, 0.5], color=(darkness[i], darkness[i], darkness[i]), linewidth=3) # 设置x轴格式 ax = plt.gca() ax.xaxis.set_major_locator(DayLocator()) ax.xaxis.set_major_formatter(DateFormatter("%Y-%m-%d")) ax.xaxis.set_minor_locator(HourLocator(interval=2)) ax.xaxis.set_minor_formatter(DateFormatter("%H")) # 调整样式 plt.xlabel("Date & Time") plt.yticks([]) # 隐藏无意义的y轴 plt.title("24-Hour Activity Timeline (Darker = Shorter Interval)") plt.legend() plt.grid(axis='x', linestyle='--', alpha=0.6) plt.xticks(rotation=45) plt.tight_layout() plt.show()
3. 大规模多用户数据集优化实现
如果数据集包含多个respondent_id,可按用户分组绘制子图:
import pandas as pd # 模拟多用户数据集 df = pd.DataFrame({ 'respondent_id': ["1086624"]*6 + ["1086625"]*4, 'fulldate': pd.to_datetime(call_times + ["2023-11-21 09:00:00", "2023-11-21 09:15:00", "2023-11-21 10:00:00", "2023-11-21 10:30:00"]) }) # 按用户分组绘制子图 fig, axes = plt.subplots(nrows=2, ncols=1, figsize=(12, 10)) for idx, (user_id, group) in enumerate(df.groupby('respondent_id')): ax = axes[idx] dates = sorted(group['fulldate']) dates_num = date2num(dates) time_deltas = np.diff(dates_num) * 86400 norm_deltas = time_deltas / time_deltas.max() darkness = 1 - norm_deltas ax.scatter(dates_num, [0.5]*len(dates_num), color='gray', alpha=0.7) for i in range(len(dates)-1): ax.plot([dates_num[i], dates_num[i+1]], [0.5, 0.5], color=(darkness[i], darkness[i], darkness[i]), linewidth=3) ax.xaxis.set_major_locator(DayLocator()) ax.xaxis.set_major_formatter(DateFormatter("%Y-%m-%d")) ax.xaxis.set_minor_locator(HourLocator(interval=2)) ax.xaxis.set_minor_formatter(DateFormatter("%H")) ax.set_title(f"User {user_id} Activity Timeline") ax.set_yticks([]) ax.grid(axis='x', linestyle='--', alpha=0.6) plt.tight_layout() plt.show()
4. R语言实现方案
如果偏好R,可用ggplot2实现:
library(ggplot2) library(lubridate) # 示例数据 call_times <- c( "2023-11-19 08:00:00", "2023-11-19 08:10:00", "2023-11-19 08:30:00", "2023-11-19 09:00:00", "2023-11-20 10:00:00", "2023-11-20 11:00:00" ) dates <- ymd_hms(call_times) %>% sort() # 生成间隔数据框 interval_df <- data.frame( start = dates[-length(dates)], end = dates[-1], delta = as.numeric(difftime(dates[-1], dates[-length(dates)], units = "secs")) ) interval_df$norm_delta <- interval_df$delta / max(interval_df$delta) interval_df$darkness <- 1 - interval_df$norm_delta # 绘制图形 ggplot() + geom_segment(data = interval_df, aes(x = start, xend = end, y = 1, yend = 1, color = I(rgb(darkness, darkness, darkness))), linewidth = 3) + geom_point(aes(x = dates, y = 1), color = "gray", alpha = 0.7) + scale_x_datetime(date_breaks = "1 day", date_labels = "%Y-%m-%d", minor_breaks = "2 hours", minor_labels = "%H") + theme_minimal() + theme(axis.text.y = element_blank(), axis.title.y = element_blank(), axis.title.x = element_text(size=12), plot.title = element_text(size=14, hjust=0.5)) + labs(x = "Date & Time", title = "24-Hour Activity Timeline (Darker = Shorter Interval)")
内容的提问来源于stack exchange,提问作者nill
相关产品推荐
相关产品推荐

