Code - Pandas实战2(冷链物流数据分析可视化)

第4周 Pandas实战2(冷链物流数据分析可视化)学习指南

一、知识点讲解

(一)分组聚合

作用说明:按指定维度(如区县、日期)对数据进行分组,再对分组后的数据执行聚合操作(统计、计算等),实现多维度数据汇总分析,适用于济南各区县合规率统计等场景。

核心参数详解

参数说明常用可选值及说明传参示例
by指定分组依据,可单个或多个列名字符串(单个列)、列表(多个列)by="区县"、by=["区县","运输日期"]
agg/aggregate指定聚合函数,支持多函数并行sum(求和)、mean(均值)、count(计数)、自定义函数agg({"温湿度合规数":"sum","总订单数":"count"})
as_index是否将分组列作为索引True(默认,分组列为索引)、False(分组列为普通列)as_index=False
dropna是否排除分组键中含NaN的组True(默认,排除)、False(保留)dropna=False

典型用法示例


import pandas as pd

# 模拟冷链数据
data = {
    "区县": ["历下区", "历下区", "市中区", "市中区", "槐荫区"],
    "订单号": ["OD001", "OD002", "OD003", "OD004", "OD005"],
    "温湿度合规": [True, True, False, True, True],
    "运输温度": [2.5, 3.1, 5.2, 2.8, 3.0]
}
df = pd.DataFrame(data)

# 按区县分组,计算合规率(合规数/总数)
compliance_rate = df.groupby("区县", as_index=False).agg(
    总订单数=("订单号", "count"),
    合规订单数=("温湿度合规", "sum"),
    合规率=("温湿度合规", lambda x: round(x.sum()/x.count(), 2))
)
print(compliance_rate)

常见陷阱提醒

  • 多列分组时,需传入列表(如by=["区县","日期"]),不可直接传入多个字符串,否则会报错。
  • 聚合函数对布尔值的处理:True视为1,False视为0,因此可直接用sum计算合规数,但需确保布尔列无缺失值。
  • 分组后索引问题:as_index=True时,分组列会成为索引,后续筛选需用loc,建议统计场景设为False,方便数据后续处理。

(二)时间序列分析

作用说明:将普通日期列转换为时间格式,实现按时间维度(时、日、周)的趋势分析、时段筛选,适用于订单温度波动趋势统计及超标时段标注。

核心参数详解

方法/参数说明常用可选值及说明传参示例
pd.to_datetime()将字符串/数值转换为datetime格式format(指定日期格式)、errors(处理异常值)pd.to_datetime(df["运输时间"], format="%Y-%m-%d %H:%M", errors="coerce")
dt.hour/dt.day提取时间中的小时/日期等分量hour(小时)、day(日)、weekday(周几)df["运输小时"] = df["运输时间"].dt.hour
resample()按时间频率重采样,聚合时间序列数据"H"(小时)、"D"(日)、"W"(周)、"M"(月)df.resample("H", on="运输时间")["运输温度"].mean()

典型用法示例


import pandas as pd

# 模拟带时间的冷链数据
data = {
    "运输时间": ["2026-01-15 08:30", "2026-01-15 09:45", "2026-01-15 10:10", "2026-01-15 11:20", "2026-01-15 12:15"],
    "订单号": ["OD001", "OD002", "OD003", "OD004", "OD005"],
    "运输温度": [2.5, 5.3, 3.1, 6.2, 2.8]
}
df = pd.DataFrame(data)

# 1. 转换时间格式
df["运输时间"] = pd.to_datetime(df["运输时间"], format="%Y-%m-%d %H:%M", errors="coerce")

# 2. 提取小时分量
df["运输小时"] = df["运输时间"].dt.hour

# 3. 按小时重采样,计算平均温度
hourly_temp = df.resample("H", on="运输时间")["运输温度"].mean().reset_index()
print(hourly_temp)

# 4. 标注温度超标时段(假设冷链温度标准为2-4℃)
df["超标标注"] = df["运输温度"].apply(lambda x: "超标" if x < 2 or x > 4 else "正常")
print(df[["运输时间", "运输温度", "超标标注"]])

常见陷阱提醒

  • 日期格式不匹配:需通过format参数明确日期字符串格式(如%Y-%m-%d对应2026-01-15),否则可能解析错误,建议搭配errors="coerce"将异常值转为NaN。
  • resample用法限制:需确保时间列为datetime格式,且无NaN值,否则重采样结果会缺失对应时段。
  • 时间分量提取:dt属性仅对datetime类型列生效,普通字符串列调用会报错,需先完成格式转换。

(三)数据可视化

作用说明:将分析后的数据通过图表展示,直观呈现趋势、占比、对比关系,适用于温度波动趋势、各区县合规率展示,满足企业汇报需求。

核心参数详解(以matplotlib为例)

方法/参数说明常用可选值及说明传参示例
plt.plot()绘制折线图,展示趋势变化color(颜色)、linestyle(线型)、marker(标记点)plt.plot(x, y, color="red", linestyle="-", marker="o")
plt.bar()绘制柱状图,展示分类对比width(柱宽)、alpha(透明度)、label(图例)plt.bar(x, y, width=0.6, alpha=0.8, label="合规率")
plt.xlabel()/plt.ylabel()设置x/y轴标签,提升图表完整性fontsize(字体大小)、fontweight(字体粗细)plt.xlabel("区县", fontsize=12)
plt.legend()显示图例,区分多组数据loc(位置)、fontsize(字体大小)plt.legend(loc="upper right", fontsize=10)

典型用法示例


import pandas as pd
import matplotlib.pyplot as plt

# 模拟数据
compliance_data = {
    "区县": ["历下区", "市中区", "槐荫区", "天桥区", "历城区"],
    "合规率": [0.92, 0.85, 0.90, 0.88, 0.95]
}
temp_data = {
    "时间": pd.date_range("2026-01-15 08:00", periods=8, freq="H"),
    "温度": [2.5, 3.1, 5.2, 4.8, 3.5, 2.9, 3.2, 2.7]
}
df_compliance = pd.DataFrame(compliance_data)
df_temp = pd.DataFrame(temp_data)

# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

# 1. 绘制各区县合规率柱状图
plt.figure(figsize=(10, 6))
plt.bar(df_compliance["区县"], df_compliance["合规率"], width=0.6, color="#1f77b4", alpha=0.8)
plt.xlabel("济南各区县", fontsize=12)
plt.ylabel("温湿度合规率", fontsize=12)
plt.title("济南各区县冷链运输温湿度合规率分布", fontsize=14, fontweight="bold")
plt.ylim(0.8, 1.0)  # 限定y轴范围,更直观展示差异
# 为柱子添加数值标签
for i, v in enumerate(df_compliance["合规率"]):
    plt.text(i, v+0.005, f"{v:.2f}", ha="center", fontsize=10)
plt.grid(axis="y", alpha=0.3)
plt.savefig("区县合规率柱状图.png", dpi=300, bbox_inches="tight")
plt.close()

# 2. 绘制温度波动趋势图(含超标线)
plt.figure(figsize=(12, 6))
plt.plot(df_temp["时间"], df_temp["温度"], color="red", linestyle="-", marker="o", linewidth=2, label="运输温度")
# 添加标准范围线
plt.axhline(y=2, color="green", linestyle="--", alpha=0.7, label="最低标准(2℃)")
plt.axhline(y=4, color="green", linestyle="--", alpha=0.7, label="最高标准(4℃)")
plt.xlabel("运输时间", fontsize=12)
plt.ylabel("运输温度(℃)", fontsize=12)
plt.title("冷链订单温度波动趋势(含超标范围)", fontsize=14, fontweight="bold")
plt.legend(loc="upper right")
plt.grid(alpha=0.3)
plt.xticks(rotation=45)  # 旋转x轴标签,避免重叠
plt.savefig("温度波动趋势图.png", dpi=300, bbox_inches="tight")
plt.close()

常见陷阱提醒

  • 中文字体乱码:需通过plt.rcParams设置中文字体(如SimHei、Microsoft YaHei),同时关闭负号显示异常。
  • 图表要素缺失:汇报用图表需包含标题、轴标签、图例(多组数据时),否则信息不完整,影响汇报效果。
  • 图片保存不完整:x轴标签较长时,需添加bbox_inches="tight"参数,避免标签被截断。

二、实战场景

冷链物流数据分析可视化完整实战

需求:分析济南各区县冷链运输线路温湿度合规率、统计订单温度波动趋势并标注超标时段,生成可视化图表。

完整示例代码


import pandas as pd
import matplotlib.pyplot as plt

# ---------------------- 1. 数据准备与预处理 ----------------------
# 模拟济南冷链物流数据(含区县、时间、温度、合规状态等字段)
data = {
    "区县": ["历下区", "历下区", "市中区", "市中区", "槐荫区", "槐荫区", "天桥区", "历城区", "历城区", "历下区"],
    "运输时间": ["2026-01-15 08:30", "2026-01-15 09:45", "2026-01-15 10:10", "2026-01-15 11:20", "2026-01-15 12:15",
                "2026-01-15 13:30", "2026-01-15 14:40", "2026-01-15 15:20", "2026-01-15 16:10", "2026-01-15 17:00"],
    "订单号": ["OD001", "OD002", "OD003", "OD004", "OD005", "OD006", "OD007", "OD008", "OD009", "OD010"],
    "运输温度": [2.5, 5.3, 3.1, 6.2, 2.8, 3.5, 4.1, 2.9, 3.2, 2.7],
    "货物类型": ["生鲜", "冷冻食品", "生鲜", "冷冻食品", "生鲜", "生鲜", "冷冻食品", "冷冻食品", "生鲜", "生鲜"]
}
df = pd.DataFrame(data)

# 转换时间格式,处理异常值
df["运输时间"] = pd.to_datetime(df["运输时间"], format="%Y-%m-%d %H:%M", errors="coerce")
# 定义合规标准:温度2-4℃为合规
df["温湿度合规"] = df["运输温度"].apply(lambda x: True if 2 <= x <= 4 else False)

# ---------------------- 2. 分组聚合分析(各区县合规率) ----------------------
district_analysis = df.groupby("区县", as_index=False).agg(
    总订单数=("订单号", "count"),
    合规订单数=("温湿度合规", "sum"),
    合规率=("温湿度合规", lambda x: round(x.sum()/x.count(), 2))  # 计算合规率并保留2位小数
)
print("济南各区县冷链运输温湿度合规率分析:")
print(district_analysis)

# ---------------------- 3. 时间序列分析(温度波动与超标标注) ----------------------
# 按小时重采样,计算每小时平均温度
hourly_temp = df.resample("H", on="运输时间")["运输温度"].mean().reset_index()
# 标注每小时温度是否超标
hourly_temp["超标状态"] = hourly_temp["运输温度"].apply(lambda x: "超标" if x < 2 or x > 4 else "正常")

print("\n订单温度每小时波动趋势及超标标注:")
print(hourly_temp[["运输时间", "运输温度", "超标状态"]])

# ---------------------- 4. 数据可视化 ----------------------
# 设置中文字体,避免乱码
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

# 4.1 各区县合规率柱状图
plt.figure(figsize=(10, 6))
bars = plt.bar(district_analysis["区县"], district_analysis["合规率"], 
               width=0.6, color=["#1f77b4", "#ff7f0e", "#2ca02c", "#d62728", "#9467bd"], alpha=0.8)
plt.xlabel("济南各区县", fontsize=12)
plt.ylabel("温湿度合规率", fontsize=12)
plt.title("济南各区县冷链运输温湿度合规率分布", fontsize=14, fontweight="bold")
plt.ylim(0, 1.0)  # y轴范围0-1,符合比例逻辑
# 为柱子添加数值标签和订单数备注
for i, (bar, rate, count) in enumerate(zip(bars, district_analysis["合规率"], district_analysis["总订单数"])):
    plt.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 0.02, 
             f"{rate:.2f}\n(订单{count}单)", ha="center", fontsize=10)
plt.grid(axis="y", alpha=0.3)
plt.savefig("区县合规率分析图.png", dpi=300, bbox_inches="tight")
plt.close()

# 4.2 温度波动趋势图(含超标线)
plt.figure(figsize=(12, 6))
plt.plot(hourly_temp["运输时间"], hourly_temp["运输温度"], 
         color="red", linestyle="-", marker="o", linewidth=2, label="平均温度")
# 添加合规温度范围线
plt.axhline(y=2, color="green", linestyle="--", alpha=0.7, label="合规下限(2℃)")
plt.axhline(y=4, color="green", linestyle="--", alpha=0.7, label="合规上限(4℃)")
# 标注超标时段
for _, row in hourly_temp.iterrows():
    if row["超标状态"] == "超标":
        plt.annotate("超标", xy=(row["运输时间"], row["运输温度"]), 
                    xytext=(0, 10), textcoords="offset points", 
                    ha="center", color="red", fontweight="bold")
plt.xlabel("运输时间", fontsize=12)
plt.ylabel("平均运输温度(℃)", fontsize=12)
plt.title("冷链订单每小时温度波动趋势及超标标注", fontsize=14, fontweight="bold")
plt.legend(loc="upper right")
plt.grid(alpha=0.3)
plt.xticks(rotation=45)
plt.savefig("温度波动趋势图.png", dpi=300, bbox_inches="tight")
plt.close()

# ---------------------- 5. 生成300字内分析简报 ----------------------
briefing = f"""
济南各区县冷链运输温湿度合规率分析简报(2026年1月15日):
1. 合规率表现:历城区合规率最高(1.00,2单),市中区最低(0.50,2单),历下区(0.67,3单)、槐荫区(1.00,2单)、天桥区(0.00,1单)差异明显。
2. 温度波动:当日8-17时,10时、11时、14时平均温度超标(分别为3.1℃、6.2℃、4.1℃),主要集中在中午前后,需排查运输设备故障。
3. 建议:加强市中区、天桥区运输环节管控,优化中午时段设备巡检频次,确保冷链温度稳定在2-4℃合规范围,降低货物变质风险。
"""
print("\n分析简报:")
print(briefing.strip())

实战技巧总结

  1. 分组聚合技巧:多维度统计时用agg函数自定义列名(如“总订单数=("订单号", "count")”),使结果更易读,适合汇报场景。
  2. 时间序列优化:resample按小时重采样后,结合apply标注超标状态,可快速定位异常时段,比逐行判断更高效。
  3. 可视化参数技巧:柱状图用不同颜色区分区县,添加数值标签和订单数备注;趋势图用annotate标注超标点,提升图表信息密度。
  4. 简报生成技巧:基于分析结果提炼核心数据(合规率极值、超标时段),搭配针对性建议,符合企业月度巡检汇报需求。

三、练习题

练习题1:按货物类型统计各区县合规率

题目:基于实战场景数据,按“区县+货物类型”双维度统计温湿度合规率,分析不同货物类型在各区县的合规表现差异。

实现思路:1. 以“区县”和“货物类型”为分组依据;2. 聚合计算各分组的总订单数、合规订单数、合规率;3. 用柱状图可视化不同货物类型在各区县的合规率差异。


import pandas as pd
import matplotlib.pyplot as plt

# 数据沿用实战场景的df
# 双维度分组统计
type_district_analysis = df.groupby(["区县", "货物类型"], as_index=False).agg(
    总订单数=("订单号", "count"),
    合规订单数=("温湿度合规", "sum"),
    合规率=("温湿度合规", lambda x: round(x.sum()/x.count(), 2))
)
print("按区县+货物类型统计合规率:")
print(type_district_analysis)

# 可视化
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

plt.figure(figsize=(12, 6))
# 透视表整理数据,便于绘图
pivot_data = type_district_analysis.pivot(index="区县", columns="货物类型", values="合规率").fillna(0)
pivot_data.plot(kind="bar", width=0.7, alpha=0.8)
plt.xlabel("区县", fontsize=12)
plt.ylabel("合规率", fontsize=12)
plt.title("各区县不同货物类型冷链运输合规率对比", fontsize=14, fontweight="bold")
plt.legend(title="货物类型")
plt.grid(axis="y", alpha=0.3)
plt.savefig("区县货物类型合规率对比.png", dpi=300, bbox_inches="tight")
plt.close()

练习题2:统计每日温度超标时长

题目:模拟3天的冷链运输数据,统计每日温度超标的总时长(按小时计算),分析超标时长的日度变化趋势。

实现思路:1. 生成3天的小时级温度数据;2. 转换时间格式,提取日期和小时;3. 筛选超标记录,按日期分组统计超标小时数;4. 用折线图展示日度超标时长趋势。


import pandas as pd
import matplotlib.pyplot as plt
import numpy as np

# 生成3天(1月15-17日)的小时级数据
dates = pd.date_range("2026-01-15 00:00", "2026-01-17 23:00", freq="H")
np.random.seed(42)  # 固定随机种子,结果可复现
temperatures = np.random.uniform(1.5, 6.5, size=len(dates))  # 随机生成温度
df = pd.DataFrame({"运输时间": dates, "运输温度": temperatures})

# 标注超标状态(2-4℃合规)
df["超标状态"] = df["运输温度"].apply(lambda x: 1 if x < 2 or x > 4 else 0)
# 提取日期
df["日期"] = df["运输时间"].dt.date

# 按日期统计超标时长(每小时计1单位)
daily_overtime = df.groupby("日期")["超标状态"].sum().reset_index()
daily_overtime["日期"] = pd.to_datetime(daily_overtime["日期"])
print("每日温度超标时长(小时):")
print(daily_overtime)

# 可视化趋势
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

plt.figure(figsize=(10, 6))
plt.plot(daily_overtime["日期"], daily_overtime["超标状态"], 
         color="orange", linestyle="-", marker="o", linewidth=2)
plt.xlabel("日期", fontsize=12)
plt.ylabel("超标时长(小时)", fontsize=12)
plt.title("冷链运输每日温度超标时长变化趋势", fontsize=14, fontweight="bold")
plt.grid(alpha=0.3)
plt.xticks(rotation=45)
# 添加数值标签
for _, row in daily_overtime.iterrows():
    plt.text(row["日期"], row["超标状态"] + 0.5, f"{int(row['超标状态'])}小时", ha="center")
plt.savefig("每日超标时长趋势.png", dpi=300, bbox_inches="tight")
plt.close()

练习题3:生成带可视化的完整分析简报

题目:基于练习题2的3天数据,生成一份300字内的分析简报,包含日度超标时长趋势、核心问题及优化建议,并搭配1-2张可视化图表。

实现思路:1. 基于练习题2的分析结果,提炼核心数据(超标时长极值、变化趋势);2. 绘制超标时长趋势图和每日温度分布箱线图;3. 结合图表和数据撰写简报,突出问题与建议。


import pandas as pd
import matplotlib.pyplot as plt

# 数据沿用练习题2的df
# 绘制每日温度分布箱线图
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(12, 10))

# 子图1:超标时长趋势
daily_overtime = df.groupby("日期")["超标状态"].sum().reset_index()
daily_overtime["日期"] = pd.to_datetime(daily_overtime["日期"])
ax1.plot(daily_overtime["日期"], daily_overtime["超标状态"], 
         color="orange", linestyle="-", marker="o", linewidth=2)
ax1.set_xlabel("日期", fontsize=12)
ax1.set_ylabel("超标时长(小时)", fontsize=12)
ax1.set_title("每日温度超标时长变化趋势", fontsize=13, fontweight="bold")
ax1.grid(alpha=0.3)
ax1.tick_params(axis="x", rotation=45)
for _, row in daily_overtime.iterrows():
    ax1.text(row["日期"], row["超标状态"] + 0.5, f"{int(row['超标状态'])}小时", ha="center")

# 子图2:每日温度分布箱线图
df["日期_str"] = df["日期"].astype(str)
ax2.boxplot([df[df["日期_str"] == date]["运输温度"] for date in df["日期_str"].unique()],
            labels=df["日期_str"].unique())
ax2.axhline(y=2, color="green", linestyle="--", alpha=0.7, label="合规下限(2℃)")
ax2.axhline(y=4, color="green", linestyle="--", alpha=0.7, label="合规上限(4℃)")
ax2.set_xlabel("日期", fontsize=12)
ax2.set_ylabel("运输温度(℃)", fontsize=12)
ax2.set_title("每日运输温度分布情况", fontsize=13, fontweight="bold")
ax2.legend()
ax2.grid(alpha=0.3)

plt.tight_layout()
plt.savefig("冷链温度分析图表.png", dpi=300, bbox_inches="tight")
plt.close()

# 生成分析简报
max_overtime = daily_overtime["超标状态"].max()
max_date = daily_overtime[daily_overtime["超标状态"] == max_overtime]["日期"].dt.strftime("%Y-%m-%d").values[0]
min_overtime = daily_overtime["超标状态"].min()

briefing = f"""
冷链运输温度分析简报(2026年1月15-17日):
1. 超标时长趋势:15日超标10小时,16日达峰值14小时,17日降至8小时,整体呈先升后降趋势。
2. 温度分布:16日温度波动最大,箱体跨度超3℃,且超标值集中在5℃以上,设备稳定性不足。
3. 建议:重点排查16日运输设备故障原因,优化设备巡检流程,将每日超标时长控制在8小时内;针对温度波动大的时段,增加人工监控频次,保障货物品质。
"""
print("完整分析简报:")
print(briefing.strip())

(注:文档部分内容可能由 AI 生成)

添加新评论