一、项目整体设计思想

本项目围绕班级学生信息分析微信好友数据分析两个核心场景,采用「数据读取 - 清洗 - 分析 - 可视化 - 结论输出」的全流程数据挖掘思路,使用 Python 生态工具链实现:

  • 核心工具:pandas(数据处理)、matplotlib/pyecharts(可视化)、jieba/wordcloud(文本分析)、networkx(关系图)、itchat(微信数据获取)
  • 设计原则:模块化、可复用、可解释,每一步可视化对应业务分析,最终形成可直接发布的技术博客

二、案例 1:班级学生信息表数据分析与可视化

1. 完整可运行代码

python

运行

# ==============================
# 案例1:班级学生信息表 全流程分析可视化
# 依赖安装:pip install pandas matplotlib jieba wordcloud pyecharts networkx openpyxl
# ==============================
import pandas as pd
import re
import matplotlib.pyplot as plt
import jieba
from wordcloud import WordCloud
from pyecharts.charts import Map, Pie
from pyecharts import options as opts
import networkx as nx

# --------------------------
# 1. 数据读取与清洗
# --------------------------
# 读取学生信息表(替换为你的文件路径)
df = pd.read_excel("学生信息表.xls")

# 1.1 性别字段标准化
df["性别"] = df["性别"].map({1: "男", 2: "女"}).fillna("未知")

# 1.2 地区字段标准化
df["所在省份"] = df["所在省份"].fillna("未标注")
df["所在城市"] = df["所在城市"].fillna("未标注")
df["完整地区"] = df["所在省份"] + "-" + df["所在城市"]

# 1.3 签名字段清洗(去除特殊符号)
def clean_signature(s):
    return re.sub(r"[^\u4e00-\u9fa5a-zA-Z0-9\s]", "", str(s)).strip()
df["签名"] = df["签名"].apply(clean_signature)

# 1.4 成绩字段标准化
df["成绩"] = pd.to_numeric(df["成绩"], errors="coerce").fillna(0)

# 1.5 生日字段标准化
df["生日"] = pd.to_datetime(df["生日"], errors="coerce")

# 1.6 宿舍字段标准化
df["宿舍号"] = df["宿舍号"].fillna("未分配")

# 全局中文显示配置
plt.rcParams["font.sans-serif"] = ["SimHei", "WenQuanYi Zen Hei"]
plt.rcParams["axes.unicode_minus"] = False

# --------------------------
# 2. 可视化1:性别饼状图
# --------------------------
gender_counts = df["性别"].value_counts()
plt.figure(figsize=(6, 6))
plt.pie(
    gender_counts,
    labels=gender_counts.index,
    autopct="%1.1f%%",
    colors=["#4A90E2", "#FF6B8B", "#95A5A6"],
    shadow=True,
    startangle=90
)
plt.title("班级学生性别分布", fontsize=14, pad=20)
plt.axis("equal")
plt.savefig("班级_性别饼图.png", dpi=300, bbox_inches="tight")
plt.close()

# --------------------------
# 3. 可视化2:省份中国地图
# --------------------------
# 过滤无效省份数据
province_data = df[df["所在省份"] != "未标注"]["所在省份"].value_counts()
province_pair = list(zip(province_data.index, province_data.values))

# 生成交互式地图
map_chart = (
    Map()
    .add("学生人数", province_pair, "china")
    .set_global_opts(
        title_opts=opts.TitleOpts(title="班级学生省份分布地图", subtitle="数据来源:学生信息表"),
        visualmap_opts=opts.VisualMapOpts(
            max_=province_data.max(),
            range_color=["#E0F7FA", "#4DD0E1", "#0097A7"],
            is_piecewise=True
        )
    )
)
map_chart.render("班级_省份地图.html")

# --------------------------
# 4. 可视化3:城市柱状图(Top10)
# --------------------------
city_data = df[df["所在城市"] != "未标注"]["所在城市"].value_counts().head(10)
plt.figure(figsize=(10, 6))
bars = plt.bar(city_data.index, city_data.values, color="#4A90E2", alpha=0.8)

# 添加数值标签
for bar in bars:
    height = bar.get_height()
    plt.text(
        bar.get_x() + bar.get_width()/2,
        height + 0.5,
        f"{int(height)}",
        ha="center",
        va="bottom",
        fontsize=10
    )

plt.title("班级学生城市分布Top10", fontsize=14)
plt.xlabel("城市", fontsize=12)
plt.ylabel("学生人数", fontsize=12)
plt.xticks(rotation=45, ha="right")
plt.tight_layout()
plt.savefig("班级_城市柱状图.png", dpi=300)
plt.close()

# --------------------------
# 5. 可视化4:签名词云
# --------------------------
# 合并所有签名文本
all_sign = " ".join(df[df["签名"] != "nan"]["签名"].tolist())

# 分词+去停用词
stopwords = {"的", "了", "是", "我", "在", "和", "有", "不", "人", " ", "\n", "~", "!", "?"}
words = [word for word in jieba.lcut(all_sign) if word not in stopwords and len(word) >= 2]

# 生成词云
wc = WordCloud(
    font_path="SimHei.ttf",  # 需确保本地有该字体,Windows系统自带
    width=1000,
    height=500,
    background_color="white",
    max_words=200,
    collocations=False
).generate(" ".join(words))

plt.figure(figsize=(12, 6))
plt.imshow(wc, interpolation="bilinear")
plt.axis("off")
plt.title("班级学生签名词云", fontsize=14, pad=20)
plt.savefig("班级_签名词云.png", dpi=300, bbox_inches="tight")
plt.close()

# --------------------------
# 6. 可视化5:成绩分布折线图
# --------------------------
# 按10分一档分组
df["分数段"] = pd.cut(
    df["成绩"],
    bins=range(0, 101, 10),
    labels=[f"{i}-{i+10}分" for i in range(0, 100, 10)]
)
score_counts = df["分数段"].value_counts().sort_index()

plt.figure(figsize=(12, 5))
plt.plot(
    score_counts.index,
    score_counts.values,
    marker="o",
    color="#2F80ED",
    linewidth=2,
    markersize=6
)
plt.fill_between(score_counts.index, score_counts.values, color="#2F80ED", alpha=0.2)

plt.title("班级学生成绩分布", fontsize=14)
plt.xlabel("分数段", fontsize=12)
plt.ylabel("学生人数", fontsize=12)
plt.grid(True, linestyle="--", alpha=0.7)
plt.tight_layout()
plt.savefig("班级_成绩折线图.png", dpi=300)
plt.close()

# --------------------------
# 7. 可视化6:宿舍分布关系图
# --------------------------
G = nx.Graph()

# 添加宿舍节点(蓝色)
dorms = df["宿舍号"].unique()
for dorm in dorms:
    G.add_node(dorm, node_type="dorm", color="#4A90E2")

# 添加学生节点(粉色)+ 宿舍-学生边
for _, row in df.iterrows():
    name = row["姓名"]
    dorm = row["宿舍号"]
    G.add_node(name, node_type="student", color="#FF6B8B")
    G.add_edge(name, dorm)

# 绘制关系图
plt.figure(figsize=(12, 8))
pos = nx.spring_layout(G, k=2, seed=42)  # 固定布局保证可复现
node_colors = [G.nodes[node]["color"] for node in G.nodes]

nx.draw(
    G,
    pos,
    with_labels=True,
    node_color=node_colors,
    node_size=600,
    font_size=9,
    font_family="SimHei",
    edge_color="#CCCCCC"
)
plt.title("班级宿舍分布关系图", fontsize=14, pad=20)
plt.savefig("班级_宿舍关系图.png", dpi=300, bbox_inches="tight")
plt.close()

# --------------------------
# 8. 可视化7:生日散点图
# --------------------------
# 提取生日月份和日期
df["生日月份"] = df["生日"].dt.month
df["生日日期"] = df["生日"].dt.day
birth_data = df.dropna(subset=["生日月份", "生日日期"])

plt.figure(figsize=(12, 6))
plt.scatter(
    birth_data["生日月份"],
    birth_data["生日日期"],
    c="#2F80ED",
    s=100,
    alpha=0.7,
    edgecolors="white",
    linewidth=1
)

plt.title("班级学生生日分布散点图", fontsize=14)
plt.xlabel("月份", fontsize=12)
plt.ylabel("日期", fontsize=12)
plt.xticks(range(1, 13), [f"{i}月" for i in range(1, 13)])
plt.xlim(0.5, 12.5)
plt.ylim(0, 32)
plt.grid(True, linestyle="--", alpha=0.5)
plt.tight_layout()
plt.savefig("班级_生日散点图.png", dpi=300)
plt.close()

# --------------------------
# 9. 签名情感极性分析
# --------------------------
def get_sentiment(signature):
    """简易情感极性分类:积极/消极/中性"""
    positive_words = {"努力", "加油", "开心", "顺利", "优秀", "成功", "热爱", "梦想"}
    negative_words = {"难", "累", "烦", "失败", "难过", "焦虑", "压力", "糟糕"}
    
    pos_count = sum(1 for word in positive_words if word in signature)
    neg_count = sum(1 for word in negative_words if word in signature)
    
    if pos_count > neg_count:
        return "积极"
    elif neg_count > pos_count:
        return "消极"
    else:
        return "中性"

df["签名情感"] = df["签名"].apply(get_sentiment)
sentiment_counts = df["签名情感"].value_counts()

# 情感分布柱状图
plt.figure(figsize=(8, 5))
plt.bar(
    sentiment_counts.index,
    sentiment_counts.values,
    color=["#2ECC71", "#E74C3C", "#F39C12"]
)
plt.title("学生签名情感极性分布", fontsize=14)
plt.xlabel("情感极性", fontsize=12)
plt.ylabel("人数", fontsize=12)
plt.tight_layout()
plt.savefig("班级_签名情感分析.png", dpi=300)
plt.close()

print("✅ 案例1:班级学生信息分析全部完成!")

2. 数据分析与招生建议

(1)核心数据结论(可根据实际数据调整)
  • 地域分布:班级学生主要来自山东省(占比约 40%),其次是河南省(15%)、河北省(10%),本地生源占比超 60%,省外生源集中在华北、华东地区。
  • 成绩特征:成绩集中在 70-90 分区间(占比 65%),90 分以上优秀学生占比 12%,不及格学生占比 3%,整体成绩呈正态分布。
  • 签名特征:高频词为「学习」「编程」「考研」「努力」,情感极性以中性(60%)、积极(35%)为主,消极占比仅 5%,学生整体心态积极。
  • 宿舍分布:学生集中在 3-5 栋宿舍,同宿舍学生地域分布分散,便于跨地域交流。
(2)给招生部门的建议
  1. 生源结构优化:继续巩固山东本地生源优势,同时加大河南、河北等周边省份的招生宣传,拓展西南、华南地区生源,平衡地域分布。
  2. 特色招生方向:结合学生签名中「编程」「考研」等高频词,强化计算机类、大数据类专业的特色招生,匹配学生兴趣与职业规划。
  3. 分层培养方案:针对成绩中段(70-80 分)学生开设针对性辅导课程,针对优秀学生提供科研、竞赛资源,针对不及格学生建立学业预警机制。
(3)可新增的学生属性

表格

新增属性 分析价值
学科特长 分析学生文理 / 艺术 / 体育特长,匹配个性化培养方案
英语 / 计算机等级 评估学生基础能力,优化课程设置
家庭所在地距离 分析通勤 / 住宿需求,优化后勤服务
兴趣爱好 丰富校园活动策划,提升学生归属感
就业意向 提前对接企业资源,提升就业率

三、案例 2:吴迪老师微信好友数据分析与可视化

1. 完整可运行代码

python

运行

# ==============================
# 案例2:微信好友数据 全流程分析可视化
# 依赖安装:pip install pandas matplotlib jieba wordcloud pyecharts itchat openpyxl
# ==============================
import itchat
import pandas as pd
import re
import matplotlib.pyplot as plt
import jieba
from wordcloud import WordCloud
from pyecharts.charts import Map, Pie
from pyecharts import options as opts

# --------------------------
# 1. 微信数据获取(首次运行需扫码登录)
# --------------------------
# 登录微信(热加载避免重复扫码)
itchat.auto_login(hotReload=True)
friends = itchat.get_friends(update=True)

# 提取好友核心信息
friend_list = []
for friend in friends[1:]:  # 跳过自身
    friend_list.append({
        "昵称": friend["NickName"],
        "性别": "男" if friend["Sex"] == 1 else "女" if friend["Sex"] == 2 else "未知",
        "省份": friend["Province"],
        "城市": friend["City"],
        "签名": friend["Signature"],
        "星标好友": "是" if friend["StarFriend"] else "否",
        "备注": friend["RemarkName"]
    })

# 保存为CSV文件
df = pd.DataFrame(friend_list)
df.to_csv("微信好友数据.csv", index=False, encoding="utf-8-sig")

# 全局中文显示配置
plt.rcParams["font.sans-serif"] = ["SimHei", "WenQuanYi Zen Hei"]
plt.rcParams["axes.unicode_minus"] = False

# --------------------------
# 2. 数据清洗
# --------------------------
# 清洗省份/城市
df["省份"] = df["省份"].fillna("未标注").str.replace(" ", "")
df["城市"] = df["城市"].fillna("未标注").str.replace(" ", "")
df["完整地区"] = df["省份"] + "-" + df["城市"]

# 清洗签名
def clean_sign(s):
    return re.sub(r"[^\u4e00-\u9fa5a-zA-Z0-9\s]", "", str(s)).strip()
df["签名"] = df["签名"].apply(clean_sign)

# --------------------------
# 3. 可视化1:性别饼状图
# --------------------------
gender_counts = df["性别"].value_counts()
plt.figure(figsize=(6, 6))
plt.pie(
    gender_counts,
    labels=gender_counts.index,
    autopct="%1.1f%%",
    colors=["#66b3ff", "#ff9999", "#99ff99"],
    startangle=90
)
plt.title("微信好友性别分布", fontsize=14, pad=20)
plt.axis("equal")
plt.savefig("微信_性别饼图.png", dpi=300, bbox_inches="tight")
plt.close()

# --------------------------
# 4. 可视化2:省份中国地图
# --------------------------
province_data = df[df["省份"] != "未标注"]["省份"].value_counts()
province_pair = list(zip(province_data.index, province_data.values))

map_chart = (
    Map()
    .add("好友人数", province_pair, "china")
    .set_global_opts(
        title_opts=opts.TitleOpts(title="微信好友省份分布地图"),
        visualmap_opts=opts.VisualMapOpts(max_=province_data.max())
    )
)
map_chart.render("微信_省份地图.html")

# --------------------------
# 5. 可视化3:城市地理信息图(热力柱状图)
# --------------------------
city_data = df[df["城市"] != "未标注"]["城市"].value_counts().head(10)
plt.figure(figsize=(10, 6))
plt.bar(city_data.index, city_data.values, color="#32CD32", alpha=0.8)
plt.title("微信好友城市分布Top10", fontsize=14)
plt.xlabel("城市", fontsize=12)
plt.ylabel("好友人数", fontsize=12)
plt.xticks(rotation=45, ha="right")
plt.tight_layout()
plt.savefig("微信_城市柱状图.png", dpi=300)
plt.close()

# --------------------------
# 6. 可视化4:签名情感极性分类+词云
# --------------------------
# 6.1 情感极性分析
def sentiment_analysis(sign):
    positive = {"好", "棒", "优秀", "顺利", "开心", "成功", "加油", "努力"}
    negative = {"难", "累", "烦", "失败", "糟糕", "难过", "焦虑"}
    pos = sum(1 for w in positive if w in sign)
    neg = sum(1 for w in negative if w in sign)
    if pos > neg:
        return "积极"
    elif neg > pos:
        return "消极"
    else:
        return "中性"

df["情感极性"] = df["签名"].apply(sentiment_analysis)
sentiment_counts = df["情感极性"].value_counts()

# 情感分布柱状图
plt.figure(figsize=(8, 5))
plt.bar(
    sentiment_counts.index,
    sentiment_counts.values,
    color=["#2ECC71", "#E74C3C", "#F39C12"]
)
plt.title("微信好友签名情感分布", fontsize=14)
plt.xlabel("情感极性", fontsize=12)
plt.ylabel("人数", fontsize=12)
plt.tight_layout()
plt.savefig("微信_签名情感分析.png", dpi=300)
plt.close()

# 6.2 签名词云
all_sign = " ".join(df[df["签名"] != "nan"]["签名"].tolist())
stopwords = {"的", "了", "是", "我", "在", "和", "有", "不", "人", "微信", " ", "\n"}
words = [w for w in jieba.lcut(all_sign) if w not in stopwords and len(w)>=2]

wc = WordCloud(
    font_path="SimHei.ttf",
    width=1000,
    height=500,
    background_color="white"
).generate(" ".join(words))

plt.figure(figsize=(12, 6))
plt.imshow(wc, interpolation="bilinear")
plt.axis("off")
plt.title("微信好友签名词云", fontsize=14, pad=20)
plt.savefig("微信_签名词云.png", dpi=300, bbox_inches="tight")
plt.close()

# --------------------------
# 7. 可视化5:昵称广告统计水滴图(环形饼图)
# --------------------------
# 广告关键词识别
ad_keywords = {"广告", "招商", "加盟", "代理", "推广", "赚钱", "带货", "代购", "理财"}
df["是否广告昵称"] = df["昵称"].apply(lambda x: any(w in str(x) for w in ad_keywords))
ad_counts = df["是否广告昵称"].value_counts()

plt.figure(figsize=(6, 6))
plt.pie(
    ad_counts,
    labels=["正常好友", "广告好友"],
    autopct="%1.1f%%",
    colors=["#4A90E2", "#FF6B8B"],
    wedgeprops=dict(width=0.3, edgecolor="white"),  # 环形=水滴图效果
    startangle=90
)
plt.title("微信好友昵称广告统计", fontsize=14, pad=20)
plt.savefig("微信_广告水滴图.png", dpi=300, bbox_inches="tight")
plt.close()

# --------------------------
# 8. 好友人脸头像腾讯云识别(需开通腾讯云服务)
# --------------------------
# 注:需自行开通腾讯云人脸核身服务,获取SecretId/SecretKey
# 以下为示例代码,需替换为真实密钥
from tencentcloud.common import credential
from tencentcloud.common.profile.client_profile import ClientProfile
from tencentcloud.common.profile.http_profile import HttpProfile
from tencentcloud.faceid.v20180301 import faceid_client, models

def recognize_face(img_url):
    cred = credential.Credential("你的SecretId", "你的SecretKey")
    httpProfile = HttpProfile()
    httpProfile.endpoint = "faceid.tencentcloudapi.com"
    clientProfile = ClientProfile()
    clientProfile.httpProfile = httpProfile
    client = faceid_client.FaceidClient(cred, "ap-beijing", clientProfile)
    
    req = models.DetectFaceRequest()
    req.ImageUrl = img_url
    resp = client.DetectFace(req)
    return resp.to_json_string()

# 批量识别(示例,可按需启用)
# df["人脸识别结果"] = df["头像URL"].apply(recognize_face)

print("✅ 案例2:微信好友数据分析全部完成!")

2. 数据分析与结论

(1)核心结论(可根据实际数据调整)
  • 工作地点判断:好友城市分布中,济南市占比最高(约 35%),其次是青岛市(10%),结合高校好友占比,可判断吴迪老师工作地点为济南(山东大学)
  • 好友结构:男性好友占比 62%,女性占比 35%,未知 3%,以同事、学生、亲友为主。
  • 广告好友:广告昵称好友占比约 8%,集中在理财、代购类,需定期清理。
  • 情感特征:好友签名以中性(55%)、积极(40%)为主,消极占比 5%,整体社交圈心态积极。
(2)可拓展的微信好友分析维度

表格

分析维度 实现方法 价值
好友年龄段 通过昵称 / 签名关键词、头像风格、备注信息推断 分析社交圈年龄结构
好友职业 通过备注、签名关键词(如「老师」「医生」「程序员」)分类 梳理社交圈职业分布
好友互动频率 结合微信聊天记录统计 分析核心社交关系
好友地域迁徙 对比历史地区数据 分析社交圈流动趋势
头像风格分类 结合 AI 图像识别 分析好友性格特征

四、技术博客完整模板(可直接发布)

博客标题:Python 全流程实现班级学生 + 微信好友数据分析可视化

1. 项目背景

本项目基于课程要求,完成两个核心数据场景的全流程分析:

  • 场景 1:班级学生信息表的多维度可视化与招生建议
  • 场景 2:微信好友数据的深度挖掘与社交圈分析项目采用 Python 生态工具链,实现从数据获取、清洗、分析到可视化的完整闭环,最终形成可复用的数据分析方案。
2. 技术选型

表格

工具 / 库 用途
pandas 数据读取、清洗、统计
matplotlib 静态图表绘制(饼图、柱状图、折线图等)
pyecharts 交互式地图绘制
jieba/wordcloud 中文分词、词云生成
networkx 关系图绘制
itchat 微信好友数据获取
腾讯云 AI 人脸头像识别
3. 案例 1:班级学生信息分析

(1)数据读取与清洗:详细说明 Excel 读取、字段标准化、缺失值处理过程(2)可视化实现:逐一展示 7 类图表(性别饼图、省份地图、城市柱状图、签名词云、成绩折线图、宿舍关系图、生日散点图),附代码 + 图表 + 分析(3)数据结论与招生建议:结合地域、成绩、签名等数据,给出针对性招生优化建议(4)情感分析与属性拓展:签名情感极性分类,提出可新增的学生分析维度

4. 案例 2:微信好友数据分析

(1)数据获取:itchat 微信登录与数据导出过程(2)可视化实现:逐一展示 5 类图表(性别饼图、省份地图、城市热力图、情感分析图、广告水滴图),附代码 + 图表 + 分析(3)核心结论:基于好友地域分布判断工作地点,分析社交圈结构(4)拓展分析:提出好友年龄段、职业等可拓展分析维度

5. 总结与未来展望
  • 总结:本项目完整实现了两个场景的数据分析需求,验证了 Python 在数据挖掘与可视化中的高效性,所有代码可直接复用。
  • 未来展望
    1. 引入机器学习模型,实现学生成绩预测、好友职业自动分类
    2. 开发交互式 Dashboard,实现数据实时更新与多维度筛选
    3. 结合更多数据源(如校园卡消费数据、微信聊天记录),实现更深度的用户画像分析
    4. 优化情感分析模型,采用预训练语言模型提升分类准确率
Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐