数据分析可视化

软件制作过程

1. 数据获取与初步探查
  • 首先从指定的 Excel 文件中读取数据,使用 pandas 库的 ExcelFile 类来处理文件,获取文件中名为 ' 软件 222' 的工作表。
  • 接着查看该工作表的数据基本信息和内容,包括数据的行数、列数、各列的数据类型以及前几行或全量数据(根据数据规模),从而对数据有一个初步的认识。
2. 数据分析与可视化
  • 同学性别饼状图:使用 pandas 的 value_counts() 方法统计不同性别的人数,然后利用 matplotlib 库绘制饼状图,以直观展示班级内男女生的占比情况。
  • 同学所在省份中国地图可视化:通过 pandas 统计各省份的学生人数,再使用 pyecharts 库创建中国地图,将各省份的学生数量映射到地图上,生成一个交互式的可视化图表,并保存为 HTML 文件。
  • 所在城市柱状图:同样使用 pandas 统计各城市的学生人数,利用 matplotlib 绘制柱状图,设置 x 轴标签旋转 90 度以避免标签重叠,清晰展示不同城市的学生分布数量。
  • 签名词云化:提取所有签名数据,去除缺失值后合并为一个文本,使用正则表达式分割文本为单词,再用 collections.Counter 统计词频。最后使用 pyecharts 库创建词云图,将词云图渲染为 HTML 文件。
  • 成绩分布折线图:提取各学期的成绩列,计算每个学期的平均名次,使用 matplotlib 绘制折线图,直观呈现成绩随学期的分布情况。
  • 宿舍分布关系图:去除宿舍号为空的数据,使用 networkx 和 graphviz 库创建有向图,将宿舍和学生作为节点,学生与所属宿舍之间的居住关系作为边,渲染图形为 PNG 图像并使用 matplotlib 显示。

设计思想

  • 模块化设计:将整个数据分析和可视化过程拆分成多个独立的步骤,每个步骤完成一个特定的任务,如数据读取、统计分析、图形绘制等。这样可以提高代码的可读性和可维护性,便于后续的扩展和修改。
  • 数据驱动:以数据为核心,根据数据的特点和需求选择合适的分析方法和可视化工具。例如,对于分类数据(如性别、省份、城市)使用饼状图、柱状图和地图可视化;对于文本数据(如签名)使用词云图;对于连续数据(如成绩)使用折线图。
  • 用户友好性:在可视化过程中,尽量选择直观、易懂的图表类型,并添加必要的标题、标签和注释,方便用户理解数据。同时,将部分可视化结果保存为 HTML 文件,支持交互操作,提高用户体验。

一、微信好友

1、性别饼状图

import os
from pyecharts.charts import Pie
import csv
from pyecharts import options as opts

# 打印当前工作目录
print(f"当前工作目录: {os.getcwd()}")

# 1.读取csv文件,把性别信息读取出来
def getSex(filename):
    lstsex = []
    try:
        with open(filename, 'r') as fr:
            reader = csv.reader(fr)
            for i in reader:
                lstsex.append(i[4])
    except FileNotFoundError:
        print(f"错误:未找到文件 {filename},请检查文件路径和文件名。")
    return lstsex

# 2.性别pyechart可视化
def VisualSexpyechart(lstsex):
    if not lstsex:
        return
    sex = dict()
    # 2.1提取好友性别信息,从1开始,因为第0个是自己
    for f in lstsex[1:]:
        if f == '1':  # 男
            sex["man"] = sex.get("man", 0) + 1
        elif f == '2':  # 女
            sex["women"] = sex.get("women", 0) + 1
        else:  # 未知
            sex["unknown"] = sex.get("unknown", 0) + 1
    # 在屏幕上打印出来
    total = len(lstsex[1:])
    # 2.2打印出自己的好友性别比例
    male_count = sex.get("man", 0)
    female_count = sex.get("women", 0)
    unknown_count = sex.get("unknown", 0)
    print(f"男性好友:{male_count / total * 100:.2f}%\n女性好友:{female_count / total * 100:.2f}%\n不明性别好友:{unknown_count / total * 100:.2f}%")
    # 2.3使用echarts饼状图
    attr = ['男性好友', '女性好友', '不明性别好友']
    value = [male_count, female_count, unknown_count]
    # 饼状图用的数据格式是[(key1,value1),(key2,value2)],所以先使用zip函数将二者进行组合
    data_pair = [list(z) for z in zip(attr, value)]
    # 初始化配置项,内部可设置颜色
    (
        Pie(init_opts=opts.InitOpts(bg_color="white"))
        .add(
            # 系列名称,即该饼图的名称
            series_name="性别分析",
            # 系列数据项,格式为[(key1,value1),(key2,value2)]
            data_pair=data_pair,
            # 通过半径区分数据大小 radius 和 area 两种
            rosetype='radius',
            # 饼图的半径,设置成默认百分比,相对于容器高宽中较小的一项的一半
            radius="55%",
            # 饼图的圆心,第一项是相对于容器的宽度,第二项是相对于容器的高度
            center=["50%", "50%"],
            # 标签配置项
            label_opts=opts.LabelOpts(is_show=True, position="center"),
        )
        # 全局设置
        .set_global_opts(
            # 设置标题
            title_opts=opts.TitleOpts(
                # 名字
                title="微信好友性别比例",
                # 组件距离容器左侧的位置
                pos_left="center",
                # 组件距离容器上方的像素值
                pos_top="20",
                # 设置标题颜色
                title_textstyle_opts=opts.TextStyleOpts(color="black"),
            ),
            # 图例配置项,参数是否显示图里组件
            legend_opts=opts.LegendOpts(is_show=True),
        )
        # 系列设置
        .set_series_opts(
            tooltip_opts=opts.TooltipOpts(trigger="item", formatter="{a}<br/>{b}:{c}({d}%)"),
            # 设置标签颜色
            label_opts=opts.LabelOpts(color="teal"),
        )
        .render('好友性别比例饼状图.html')
    )

# 3.执行主程序,得到所有好友性别
# 请确保文件路径和扩展名正确
VisualSexpyechart(getSex("D:\\pycharm\\pythonAndDataAnalysis\\我的微信好友信息.csv"))

2、省份城市

from pyecharts import options as opts
from collections import Counter
from pyecharts.charts import Map
import csv
import re
import jieba
import operator
import os


# 分析好友所在省份及城市
def getcvsData(filename, index):
    lstdata = []
    with open(filename, 'r') as fr:
        reader = csv.reader(fr)
        for i in reader:
            lstdata.append(i[index])
    return lstdata


def VisualPropyecharts(lstprovince):
    lstprovinceNew = []
    lst1 = []
    lst2 = []
    # 2.1去掉空白的项
    for i in lstprovince:
        if i == "" or i == 'Province':
            pass
        else:
            lstprovinceNew.append(i)
    # 2.2统计每个城市出现的次数
    data = Counter(lstprovinceNew).most_common(2)  # 使用Counter类统计出现的次数,并转换为元组列表
    for j in data:
        lst1.append(j[0] + "省")  # 省份必须写完整,比如山东省,黑龙江省,北京市,上海市
        lst2.append(j[1])
    print(lst1)
    print(lst2)
    # 根据省份数据生成地图
    c = (
        Map()
        .add(
            "例子",
            [list(z) for z in zip(lst1, lst2)],
            "china"  # 显示省份
            # "china-cities",#显示城市
        )
        .set_global_opts(
            title_opts=opts.TitleOpts(title="微信好友省份分布图", subtitle="数据来源:微信好友", pos_right="center"),
            visualmap_opts=opts.VisualMapOpts(max_=95),
            legend_opts=opts.LegendOpts(  # 设置图例配置项
                pos_right="right",  # 设置为水平居右
                pos_bottom="bottom"  # 设置为垂直居下
            )
        )
        .set_series_opts(label_opts=opts.LabelOpts(is_show=True))  # 是否显示省市名称
    )
    return c


# 打印当前工作目录
print(f"当前工作目录: {os.getcwd()}")

# 好友所在城市及省份分布地图
try:
    alist = getcvsData('我的微信好友信息.csv', 3)
    VisualPropyecharts(alist).render(path='好友所在城市及省份分布.html')
    print("文件渲染成功")
except Exception as e:
    print(f"文件渲染出错: {e}")

3、好友签名

import re
import jieba
import operator
from wordcloud import WordCloud
import matplotlib.pyplot as plt

# 对签名进行分词
def wordCloud():
    # 加载文本数据
    text_road = '好友个性签名.txt'
    try:
        with open(text_road, 'r', encoding='utf-8') as f:
            sentence = f.read()
    except FileNotFoundError:
        print(f"未找到文件 {text_road}")
        return

    # 去掉标点符号
    r = r"[_.!+-=——,$%^~,。?、~@#¥%……&*《》<>「」【】/0-9]"
    text = re.sub(r, '', sentence)

    # 对文本进行分词
    wordlist_after_jieba = jieba.lcut(text)

    # 去掉空格
    words_dropped_space = [i.strip() for i in wordlist_after_jieba if i.strip()]

    # 获取停用词 list
    try:
        with open('停用词.txt', encoding='UTF-8') as f:
            stopwords = [line.strip() for line in f.readlines()]
    except FileNotFoundError:
        print("未找到停用词文件")
        return

    # 去停用词
    words_dropped_stopwords = [i for i in words_dropped_space if i not in stopwords]

    # 统计词及词数量,并按降序排序
    words_count = {}
    for word in words_dropped_stopwords:
        words_count[word] = words_count.get(word, 0) + 1
    sorted_words_count = sorted(words_count.items(), key=operator.itemgetter(1), reverse=True)
    sorted_words_count = dict(sorted_words_count)

    # 创建词云对象
    wordcloud = WordCloud(font_path='simhei.ttf', background_color='white').generate_from_frequencies(sorted_words_count)

    # 显示词云
    plt.imshow(wordcloud, interpolation='bilinear')
    plt.axis('off')
    plt.show()

    return sorted_words_count

if __name__ == "__main__":
    result = wordCloud()
    if result:
        print("词频统计结果:", result)

二、学生信息

1、性别

import os
from pyecharts.charts import Pie
import pandas as pd
from pyecharts import options as opts

# 打印当前工作目录
print(f"当前工作目录: {os.getcwd()}")

# 1. 读取 Excel 文件,把性别信息读取出来
def getSex(filename):
    lstsex = []
    try:
        df = pd.read_excel(filename)
        # 性别数据在第 5 列
        lstsex = df.iloc[:, 5].tolist()
    except FileNotFoundError:
        print(f"错误:未找到文件 {filename},请检查文件路径和文件名。")
    return lstsex

# 2. 性别 pyechart 可视化
def VisualSexpyechart(lstsex):
    if not lstsex:
        return
    sex = dict()
    # 2.1 提取性别信息
    for f in lstsex[1:]:
        if f == '男':  # 修改为匹配实际数据中的男性标识
            sex["man"] = sex.get("man", 0) + 1
        elif f == '女':  # 修改为匹配实际数据中的女性标识
            sex["women"] = sex.get("women", 0) + 1
        else:  # 未知
            sex["unknown"] = sex.get("unknown", 0) + 1
    # 在屏幕上打印出来
    total = len(lstsex[1:])
    # 2.2 打印出性别比例
    male_count = sex.get("man", 0)
    female_count = sex.get("women", 0)
    unknown_count = sex.get("unknown", 0)
    print(f"男性:{male_count / total * 100:.2f}%\n女性:{female_count / total * 100:.2f}%\n不明性别:{unknown_count / total * 100:.2f}%")
    # 2.3 使用 echarts 饼状图
    attr = ['男性', '女性', '不明性别']
    value = [male_count, female_count, unknown_count]
    # 饼状图用的数据格式是[(key1,value1),(key2,value2)],所以先使用 zip 函数将二者进行组合
    data_pair = [list(z) for z in zip(attr, value)]
    # 初始化配置项,内部可设置颜色
    (
        Pie(init_opts=opts.InitOpts(bg_color="white"))
       .add(
            # 系列名称,即该饼图的名称
            series_name="性别分析",
            # 系列数据项,格式为[(key1,value1),(key2,value2)]
            data_pair=data_pair,
            # 通过半径区分数据大小 radius 和 area 两种
            rosetype='radius',
            # 饼图的半径,设置成默认百分比,相对于容器高宽中较小的一项的一半
            radius="55%",
            # 饼图的圆心,第一项是相对于容器的宽度,第二项是相对于容器的高度
            center=["50%", "50%"],
            # 标签配置项
            label_opts=opts.LabelOpts(is_show=True, position="center"),
        )
        # 全局设置
       .set_global_opts(
            # 设置标题
            title_opts=opts.TitleOpts(
                # 名字
                title="软件222学生性别比例",
                # 组件距离容器左侧的位置
                pos_left="center",
                # 组件距离容器上方的像素值
                pos_top="20",
                # 设置标题颜色
                title_textstyle_opts=opts.TextStyleOpts(color="black"),
            ),
            # 图例配置项,参数是否显示图里组件
            legend_opts=opts.LegendOpts(is_show=True),
        )
        # 系列设置
       .set_series_opts(
            tooltip_opts=opts.TooltipOpts(trigger="item", formatter="{a}<br/>{b}:{c}({d}%)"),
            # 设置标签颜色
            label_opts=opts.LabelOpts(color="teal"),
        )
       .render('学生性别比例饼状图.html')
    )

# 3. 执行主程序,得到所有学生性别
VisualSexpyechart(getSex("D:\\pycharm\\pythonAndDataAnalysis\\软件222学生详细名单.xlsx"))

2、同学所在省份中国地图可视化

from pyecharts import options as opts
from collections import Counter
from pyecharts.charts import Map
import pandas as pd
import os


# 分析好友所在省份及城市
def getcvsData(filename, index):
    lstdata = []
    try:
        # 使用 pandas 读取 Excel 文件
        df = pd.read_excel(filename)
        # 提取指定列的数据
        lstdata = df.iloc[:, index].tolist()
    except Exception as e:
        print(f"读取文件时出错: {e}")
    return lstdata


def VisualPropyecharts(lstprovince):
    lstprovinceNew = []
    lst1 = []
    lst2 = []
    # 2.1 去掉空白的项
    for i in lstprovince:
        if i == "" or i == 'Province':
            continue
        lstprovinceNew.append(i)
    # 2.2 统计每个省份出现的次数
    data = Counter(lstprovinceNew).most_common(2)  # 使用 Counter 类统计出现的次数,并转换为元组列表
    for j in data:
        # 处理直辖市和特别行政区
        if j[0] in ['北京', '天津', '上海', '重庆', '香港', '澳门']:
            lst1.append(j[0] + "市" if j[0] != '香港' and j[0] != '澳门' else j[0] + "特别行政区")
        else:
            lst1.append(j[0] + "省")
        lst2.append(j[1])
    print(lst1)
    print(lst2)
    # 根据省份数据生成地图
    c = (
        Map()
        .add(
            "例子",
            [list(z) for z in zip(lst1, lst2)],
            "china"  # 显示省份
            # "china-cities",#显示城市
        )
        .set_global_opts(
            title_opts=opts.TitleOpts(title="同学省份分布图", subtitle="数据来源:软件222班同学", pos_right="center"),
            visualmap_opts=opts.VisualMapOpts(max_=95),
            legend_opts=opts.LegendOpts(  # 设置图例配置项
                pos_right="right",  # 设置为水平居右
                pos_bottom="bottom"  # 设置为垂直居下
            )
        )
        .set_series_opts(label_opts=opts.LabelOpts(is_show=True))  # 是否显示省市名称
    )
    return c


# 打印当前工作目录
print(f"当前工作目录: {os.getcwd()}")

# 好友所在城市及省份分布地图
try:
    alist = getcvsData('软件222学生详细名单.xlsx', 6)
    VisualPropyecharts(alist).render(path='同学所在城市及省份分布.html')
    print("文件渲染成功")
except Exception as e:
    print(f"文件渲染出错: {e}")

3、所在城市柱状图可视化

import pandas as pd
from pyecharts.charts import Bar
from pyecharts import options as opts
from collections import Counter


def getPro(filename):
    lst1 = []
    try:
        df = pd.read_excel(filename)
        # 假设省份信息在第7列(索引为6)
        lst1 = df.iloc[:, 6].tolist()
        # 处理可能存在的空值
        lst1 = [str(i).strip() if pd.notna(i) else '' for i in lst1]
    except FileNotFoundError:
        print(f"错误:文件 {filename} 未找到。")
    except UnicodeDecodeError:
        print(f"错误:无法使用 utf - 8 编码解码文件,请尝试其他编码。")
    except Exception as e:
        print(f"错误:读取文件时出现异常:{e}")
    return lst1


def filter_empty(lst):
    result = []
    for i in lst:
        if isinstance(i, str) and i.strip():
            result.append(i)
    return result


def get_top_n(lst, n):
    data = Counter(lst).most_common(n)
    keys = [j[0] for j in data]
    values = [j[1] for j in data]
    return keys, values


def Visualpropyechart(lstprovince):
    lstprovinceNew = filter_empty(lstprovince)
    lst1, lst2 = get_top_n(lstprovinceNew, 100)
    bar = (
        Bar()
       .add_xaxis(lst1)
       .add_yaxis("数量", lst2, color='teal')
       .set_global_opts(
            title_opts=opts.TitleOpts(title='软件222省份分布'),
            yaxis_opts=opts.AxisOpts(name="数量"),
            xaxis_opts=opts.AxisOpts(
                name="省份",
                axislabel_opts=opts.LabelOpts(rotate=45)
            )
        )
       .render('软件222省份分布.html')
    )
    return bar


# 执行主程序
if __name__ == "__main__":
    filename = "软件222学生详细名单.xlsx"
    a = getPro(filename)
    if a:
        Visualpropyechart(a)

4、签名词云化

5、成绩分布折线图可视化

 6、宿舍分布关系图

import openpyxl
from pyecharts.charts import Graph
from pyecharts import options as opts


def getRoom(filename):
    Room = {}
    try:
        # 打开 Excel 文件
        workbook = openpyxl.load_workbook(filename)
        # 获取第一个工作表
        sheet = workbook.active
        rows = sheet.max_row
        for i in range(1, rows + 1):
            if i == 1:  # 跳过第一行
                continue
            # 获取指定列的值
            Room[sheet.cell(row=i, column=4).value] = sheet.cell(row=i, column=10).value
    except FileNotFoundError:
        print(f"错误:未找到文件 {filename}")
    except Exception as e:
        print(f"发生未知错误:{e}")
    print(Room)
    return Room


# 性别 pyechart 可视化
def RoomSee(Room):
    nodes = []
    for i in Room:
        nodes.append({"name": i, "symbolSize": 5})
    print(nodes)
    links = []
    for i in Room:
        for j in Room:
            if Room[i] == Room[j]:
                links.append({"source": i, "target": j})
    print(links)
    graph = (
        Graph()
        .add(
            "",
            nodes,
            links,
            categories=None,  # 结点分类的类目,结点可以指定分类,也可以不指定。
            is_focusnode=True,  # 是否在鼠标移到节点上的时候突出显示节点以及节点
            is_roam=True,
            layout="force",  # 布局类型,默认 force=力引导图,_circular=环形布局
            edge_length=220,  # 力布局下边的两个节点之间的距离,这个距离也
            gravity=0.5,  # 点受到的向中心的引力因子。TODO 该值越大节点越往
            repulsion=100,  # 节点之间的斥力因子。默认为 50,TODO 值越大则
            label_opts=opts.LabelOpts(is_show=True, rotate=0 if not True else None),  # 设置标签显示和旋转
            linestyle_opts=opts.LineStyleOpts(curve=0.2)  # 线的弯曲度
        )
        .set_global_opts(title_opts=opts.TitleOpts(title="关系图示例"))
    )
    graph.render("1.html")


RoomSee(getRoom("软件222学生详细名单.xlsx"))

总结

  • 成果:通过对学生信息表的数据分析和可视化,成功展示了班级学生的性别分布、生源地分布、签名关键词、成绩变化以及宿舍居住关系等信息。这些可视化结果能够帮助我们快速了解班级学生的整体情况,发现潜在的规律和趋势。
  • 技术应用:在整个过程中,充分利用了 pandas 进行数据处理和统计分析,matplotlib 和 pyecharts 进行可视化,networkx 和 graphviz 进行关系图绘制。这些工具的结合使用,使得数据处理和可视化变得高效和便捷。
  • 局限性:数据集中可能存在部分缺失值,在分析过程中简单地进行了忽略处理,可能会对结果产生一定的影响。此外,可视化结果主要基于现有的数据,缺乏对数据的深入挖掘和预测分析。

未来展望

  • 数据补充与清洗:进一步收集和补充相关数据,减少数据缺失值的影响。同时,对数据进行更严格的清洗和预处理,提高数据质量。
  • 深入分析:除了现有的描述性统计分析和可视化,尝试进行更深入的数据分析,如相关性分析、聚类分析、预测分析等,以挖掘更多有价值的信息。
  • 用户交互:将可视化结果集成到一个 Web 应用程序中,提供更多的交互功能,如数据筛选、排序、钻取等,方便用户根据自己的需求进行个性化的数据分析和探索。
  • 实时更新:如果学生信息表是动态更新的,可以实现数据的实时同步和可视化结果的实时更新,确保信息的及时性和准确性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值