文件目录 data_analysis_app/ ├── main.py # 主程序文件,负责启动界面和整体流程 ├── data_processing.py # 处理数据的模块,包括读取文件和数据预处理 ├── plotting.py # 绘图模块,根据用户选择绘制不同类型的图表 ├── ui.py # 界面设计模块,创建用户界面 ├── requirements.txt # 项目依赖的 Python 库列表 └── sample.csv # 用于存放示例数据文件
需要确保已经安装了 Python 环境(建议使用 Python 3.6 及以上版本),并且安装了程序所需的依赖库。上述程序主要依赖于 pandas 和 matplotlib 这两个库。 创建虚拟环境(可选但推荐) 为了避免不同项目之间的依赖冲突,你可以创建一个虚拟环境。在命令行中执行以下操作: # 创建名为 data_analysis_env 的虚拟环境 python -m venv data_analysis_env # 激活虚拟环境(Windows) data_analysis_envScriptsactivate # 激活虚拟环境(Linux/Mac) source data_analysis_env/bin/activate 在命令行中,进入 data_analysis_app 目录,然后运行 main.py 文件: cd data_analysis_app python main.py . 使用程序 选择文件:程序运行后,会弹出一个窗口,点击 “Select File” 按钮,会弹出文件选择对话框,你可以选择要分析的 CSV 或 Excel 文件。 选择图表类型:通过下拉菜单选择要绘制的图表类型,目前支持 “Bar”(柱状图)和 “Line”(折线图)。 查看结果:选择好文件和图表类型后,程序会读取文件中的数据,并绘制相应的图表展示分析结果。 5. 退出程序 关闭绘制的图表窗口后,你可以关闭程序的主窗口来退出程序。如果使用了虚拟环境,在退出程序后,你可以在命令行中执行以下命令来停用虚拟环境: # 停用虚拟环境(Windows、Linux/Mac) deactivate 要打包 Python 程序,你可以使用pyinstaller这个常用的工具 安装 pip install pyinstaller 在命令行中,进入到你的项目目录(即包含main.py文件的data_analysis_app目录),然后执行以下命令: cd 数据分析/data_analysis_app pyinstaller --onefile main.py
主窗口创建
# 创建按钮框架
button_frame = tk.Frame(root)
# 设置按钮框架的位置
button_frame.grid(row=0, column=0, columnspan=2, sticky=tk.W + tk.E, padx=5, pady=2)
# 创建打开文件按钮
open_button = tk.Button(button_frame, text="打开文件", command=select_file)
# 设置按钮的位置
open_button.pack(side=tk.LEFT, padx=3)
# 创建数据清洗按钮
clean_button = tk.Button(button_frame, text="数据清洗", command=clean_data)
# 设置按钮的位置
clean_button.pack(side=tk.LEFT, padx=3)
chart_types = list(chart_type_mapping.keys())
# 创建一个StringVar对象,用于存储当前选择的图表类型
chart_type_var = tk.StringVar(root)
# 设置默认选择的图表类型为第一个
chart_type_var.set(chart_types[0])
# 创建一个OptionMenu对象,用于选择图表类型
chart_type_menu = tk.OptionMenu(button_frame, chart_type_var, *chart_types, command=update_sub_chart_menu)
# 将OptionMenu对象放置在button_frame中,并设置位置和间距
chart_type_menu.pack(side=tk.LEFT, padx=3)
# 创建一个StringVar对象,用于存储当前选择的子图表类型
sub_chart_type_var = tk.StringVar(root)
# 创建一个OptionMenu对象,用于选择子图表类型,初始值为空
sub_chart_type_menu = tk.OptionMenu(button_frame, sub_chart_type_var, "")
# 将OptionMenu对象放置在button_frame中,并设置位置和间距
sub_chart_type_menu.pack(side=tk.LEFT, padx=3)
# 更新子图表类型菜单
update_sub_chart_menu()
按钮和菜单创建
# 创建一个列表,包含数据量的选项
data_volumes = ["10", "50", "100", "500", "1000", "全部"]
# 创建一个StringVar对象,用于存储当前选择的数据量
data_volume_var = tk.StringVar(root)
# 设置默认选择的数据量为“10”
data_volume_var.set("10")
# 创建一个OptionMenu对象,用于选择数据量
data_volume_menu = tk.OptionMenu(button_frame, data_volume_var, *data_volumes)
# 将OptionMenu对象放置在button_frame中,并设置位置和间距
data_volume_menu.pack(side=tk.LEFT, padx=3)
# 创建一个Button对象,用于生成图表
generate_button = tk.Button(button_frame, text="生成图像", command=generate_chart)
# 将Button对象放置在button_frame中,并设置位置和间距
generate_button.pack(side=tk.LEFT, padx=3)
# 创建一个Button对象,用于保存图表
save_button = tk.Button(button_frame, text="保存图像", command=save_image)
# 将Button对象放置在button_frame中,并设置位置和间距
save_button.pack(side=tk.LEFT, padx=3)
# 创建一个Button对象,用于清除显示
clear_button = tk.Button(button_frame, text="清除显示", command=clear_image)
# 将Button对象放置在button_frame中,并设置位置和间距
clear_button.pack(side=tk.LEFT, padx=3)
关键字选择区实现
# 创建垂直滚动条
scrollbar = Scrollbar(keyword_scroll_frame, orient=tk.VERTICAL)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
# 创建一个Canvas,用于显示关键字列表
keyword_frame = tk.Canvas(keyword_scroll_frame, yscrollcommand=scrollbar.set)
keyword_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
# 将滚动条与Canvas关联
scrollbar.config(command=keyword_frame.yview)
# 创建一个Frame,用于放置关键字列表
inner_frame = tk.Frame(keyword_frame)
# 将Frame放置在Canvas中
keyword_window = keyword_frame.create_window((0, 0), window=inner_frame, anchor=tk.NW)
def configure_canvas(event):
keyword_frame.update_idletasks() # 确保所有的布局更新已经完成
keyword_frame.configure(scrollregion=keyword_frame.bbox("all"))
keyword_frame.itemconfig(keyword_window, width=keyword_frame.winfo_width())
inner_frame.bind("<Configure>", configure_canvas)
keyword_frame.bind("<Configure>", configure_canvas) # 绑定画布的配置事件
image_frame = tk.Frame(root)
image_frame.grid(row=2, column=1, sticky=tk.N + tk.S + tk.E + tk.W, padx=5, pady=5)
数据读取实现
import matplotlib.pyplot as plt
import pandas as pd
import os
import sys
# 读取数据文件
def read_data(file_path):
"""
读取数据文件
:param file_path: 文件路径
:return: 读取的数据 DataFrame
"""
try:
if getattr(sys, 'frozen', False):
# 打包后的情况
base_path = sys._MEIPASS
else:
# 开发环境
base_path = os.path.dirname(os.path.abspath(__file__))
if file_path == 'sample.csv':
# 对于 sample.csv 特殊处理
full_path = os.path.join(base_path, file_path)
else:
full_path = file_path
print(f"尝试读取文件: {full_path}") # 添加调试信息
# 以默认方式读取数据
data = pd.read_csv(full_path)
return data
except Exception as e:
print(f"Error reading data: {e}")
return None
数据清洗实现
# 去除重复值
def remove_duplicates(data):
"""
去除重复值
:param data: 原始数据 DataFrame
:return: 去除重复值后的数据 DataFrame 和各列重复值数量
"""
# 避免不必要的数据复制,使用引用
duplicate_counts = {}
# 使用向量化操作计算统计信息
total_count = len(data)
unique_counts = data.nunique()
duplicate_counts_series = data.apply(lambda x: x.duplicated().sum())
value_counts_dict = {col: data[col].value_counts().to_dict() for col in data.columns}
# 构建统计信息字典
duplicate_counts = {
col: {
'总数': total_count,
'唯一值数量': unique_counts[col],
'重复值数量': duplicate_counts_series[col],
'值分布': value_counts_dict[col]
} for col in data.columns
}
# 直接去除重复行
deduplicated_data = data.drop_duplicates(keep='first')
return deduplicated_data, duplicate_counts
图表绘制函数实现
if chart_type == '柱状图':
if sub_chart_type == '簇状柱形图':
plot_data.plot(kind='bar', ax=ax)
elif sub_chart_type == '堆积柱形图':
plot_data.plot(kind='bar', stacked=True, ax=ax)
elif sub_chart_type == '百分比堆积柱形图':
plot_data_percentage = plot_data.div(plot_data.sum(axis=1), axis=0)
plot_data_percentage.plot(kind='bar', stacked=True, ax=ax)
elif chart_type == '折线图':
if sub_chart_type == '折线图':
plot_data.plot(kind='line', ax=ax)
elif sub_chart_type == '堆积折线图':
plot_data.plot(kind='line', stacked=True, ax=ax)
elif sub_chart_type == '百分比堆积折线图':
plot_data_percentage = plot_data.div(plot_data.sum(axis=1), axis=0)
plot_data_percentage.plot(kind='line', stacked=True, ax=ax)
elif chart_type == '饼图':
if sub_chart_type == '饼图':
plot_data.sum().plot(kind='pie', ax=ax)
elif sub_chart_type == '圆环图':
plot_data.sum().plot(kind='pie', ax=ax, wedgeprops=dict(width=0.3))
elif chart_type == '线条图':
if sub_chart_type == '单线条图':
if len(selected_keywords) > 0:
plot_data[selected_keywords[0]].plot(kind='line', ax=ax)
elif sub_chart_type == '多线条图':
plot_data.plot(kind='line', ax=ax)
elif chart_type == '面积图':
if sub_chart_type == '面积图':
plot_data.plot(kind='area', ax=ax)
elif sub_chart_type == '堆积面积图':
plot_data.plot(kind='area', stacked=True, ax=ax)
elif sub_chart_type == '百分比堆积面积图':
plot_data_percentage = plot_data.div(plot_data.sum(axis=1), axis=0)
plot_data_percentage.plot(kind='area', stacked=True, ax=ax)
elif chart_type == '雷达图':
文字数据处理
# 生成文本频率统计的表格数据
def generate_frequency_table(frequency_stats):
"""
生成文本频率统计的表格数据
:param frequency_stats: 文本频率统计结果,字典形式,键为列名,值为该列的频率统计 Series
:return: 包含所有频率统计信息的 DataFrame
"""
# 使用列表推导式替代嵌套循环,提高性能
table_data = [(col, value, freq)
for col, frequency in frequency_stats.items()
for value, freq in frequency.items()]
# 直接使用table_data创建DataFrame,避免append操作
return pd.DataFrame(table_data, columns=['Column', 'Value', 'Frequency'])
# 生成文本频率统计的图表
def generate_frequency_chart(frequency_stats, chart_type='bar', sub_chart_type=None):
"""
生成文本频率统计的图表
:param frequency_stats: 文本频率统计结果,字典形式,键为列名,值为该列的频率统计 Series
:param chart_type: 图表类型,默认为柱状图
:param sub_chart_type: 子图表类型
:return: 绘制的图表的 Figure 对象
"""
# 创建图表对象并设置合适的大小
fig = plt.Figure(figsize=(10, 6), dpi=100)
ax = fig.add_subplot(111)
# 优化数据转换,直接使用pandas的DataFrame构造
data = pd.DataFrame(frequency_stats)
# 使用字典映射简化图表类型判断
plot_params = {
'bar': {'kind': 'bar'},
'line': {'kind': 'line'},
'area': {'kind': 'area'},
'pie': {'kind': 'pie'}
}
打包
import os
# 项目根目录
root_dir = os.path.dirname(os.path.abspath(__file__))
# 图标文件路径
icon_path = os.path.join(root_dir, 'icon.ico')
# 主程序入口文件
main_script = os.path.join(root_dir, 'main.py')
# sample.csv 文件路径
sample_csv_path = os.path.join(root_dir, 'sample.csv')
# 需要添加的额外数据
add_data_param = f"{sample_csv_path}{os.pathsep}." if os.name == 'nt' else f"{sample_csv_path}:."
# 排除无关模块,避免打包过大或冲突
excluded_modules = [
"unittest", "torch", "tensorflow", "PyQt5", "PySide6", "IPython",
"scipy", "sphinx", "pytest", "docutils", "zmq", "cryptography",
"lxml", "sympy", "jedi"
]
exclude_modules = " ".join([f"--exclude-module={mod}" for mod in excluded_modules])
# 控制是否显示命令行窗口
no_console = "--noconsole" if os.name == 'nt' else "--windowed"
# 最终打包命令
command = f'pyinstaller --name "数据分析" --icon "{icon_path}" --onefile --add-data "{add_data_param}" {exclude_modules} {no_console} "{main_script}"'
# 打印命令,方便调试
print("打包命令:", command)
# 执行打包
os.system(command)
效果显示 
© 版权声明
文章版权归作者所有,未经允许请勿转载。如内容涉嫌侵权,请在本页底部进入<联系我们>进行举报投诉!
THE END
暂无评论内容