You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何生成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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 18:44:59