如何绘制分类变量(用户名)与时间轴的散点图?
解决用户交互时间散点图的两个核心问题
背景
我们有一个字典结构的用户交互数据:键是用户名,值是该用户的服务器交互时间戳列表(格式示例:"25-Jun-2012 01:44")。目标是绘制一张散点图:Y轴为用户名(分类变量),X轴为仅保留%H:%M的24小时制交互时间。目前在ax.scatter的x、y参数使用上有疑问,同时需要解决两个具体问题:
- pandas将列转为含日期的datetime格式后,如何仅保留
%H:%M部分? - 如何以列名作为分类变量,绘制所有列中的时间戳?
解决方案
先准备基础环境与测试数据
import pandas as pd import matplotlib.pyplot as plt import matplotlib.dates as mdates # 测试用的用户交互数据 user_interactions = { "Alice": ["25-Jun-2012 01:44", "25-Jun-2012 09:12", "26-Jun-2012 18:30"], "Bob": ["25-Jun-2012 08:20", "26-Jun-2012 10:55", "27-Jun-2012 22:15"], "Charlie": ["25-Jun-2012 14:00", "26-Jun-2012 16:45"] }
问题1:保留%H:%M部分的两种实用方式
根据需求场景不同,有两种处理思路:
- 仅需要字符串格式的
HH:MM:直接用dt.strftime提取
# 先把原始时间转成datetime格式 df = pd.DataFrame([(user, ts) for user, ts_list in user_interactions.items() for ts in ts_list], columns=["username", "timestamp"]) df["timestamp"] = pd.to_datetime(df["timestamp"], format="%d-%b-%Y %H:%M") # 提取HH:MM格式的字符串 df["time_str"] = df["timestamp"].dt.strftime("%H:%M")
- 需要保留时间的时序性(用于绘图排序):把时间转为统一日期的datetime对象(日期不影响时间轴的比较)
# 生成仅含时间的datetime(日期固定为某一天) df["time_datetime"] = pd.to_datetime(df["timestamp"].dt.strftime("%H:%M"), format="%H:%M")
问题2:以用户名(列名)为分类变量绘制散点图
核心是把宽格式的字典/数据框转成长格式(每行对应一个用户的一次交互),这样就能直接用用户名作为Y轴分类变量:
# 1. 转换为长格式数据框(如果原始是宽格式,可用pd.melt转换) df_long = pd.DataFrame([(user, ts) for user, ts_list in user_interactions.items() for ts in ts_list], columns=["username", "timestamp"]) # 2. 处理时间戳,转为带时间的datetime对象 df_long["timestamp"] = pd.to_datetime(df_long["timestamp"], format="%d-%b-%Y %H:%M") df_long["time_datetime"] = pd.to_datetime(df_long["timestamp"].dt.strftime("%H:%M"), format="%H:%M") # 3. 绘制散点图 fig, ax = plt.subplots(figsize=(10, 6)) ax.scatter(df_long["time_datetime"], df_long["username"]) # 4. 美化X轴时间显示 ax.xaxis.set_major_formatter(mdates.DateFormatter("%H:%M")) ax.xaxis.set_major_locator(mdates.HourLocator(interval=2)) # 每2小时一个刻度 # 添加标签与标题 ax.set_xlabel("交互时间(HH:MM)") ax.set_ylabel("用户名") ax.set_title("用户服务器交互时间散点图") plt.xticks(rotation=45) plt.tight_layout() plt.show()
如果你的原始数据是宽格式DataFrame(每个用户占一列),可以用pd.melt快速转长格式:
df_wide = pd.DataFrame(user_interactions) df_long = df_wide.melt(var_name="username", value_name="timestamp").dropna()
内容的提问来源于stack exchange,提问作者user136555
相关产品推荐
相关产品推荐

