学习案例主题:多组数据分析(t检验、单因素方差分析以及多重比较)python基础语法:a.主要用的语句:①if...elif...else②print ③input ④import ⑤from b.变量赋值:“=” c.注释:# 和""" """数据结构:DataFrame(pandas特有),简写df函数与模块:os.path.basename():os模块;path子模块;basename()函数调用,会执行函数并返回结果;“.”:表示“里面的”
"""Excel数据自动分析:柱状图 + 箱线图 + 显著性检验使用方法: 1. 将本脚本与Excel文件放在同一个文件夹下 2. 运行脚本,输入列名即可 3. Excel文件会自动被找到,结果保存在同一文件夹"""
Python 中,""" """(三个双引号)是多行字符串的定界符,由于字符串没有赋值给任何变量,一般会当作一个表达式,变相起到了多行注释的效果——这是 Python 中常见的一种文档注释(docstring)的写法。此处为梳理代码需求import pandas as pdimport numpy as npimport matplotlibmatplotlib.use('Agg')import matplotlib.pyplot as pltfrom scipy.stats import ttest_ind, f_onewayfrom statsmodels.stats.multicomp import pairwise_tukeyhsdimport osimport globfrom datetime import datetimeimport warningswarnings.filterwarnings('ignore')
Import是引入的意思,即搬出第1、2、3个数据库待用(第1-5行)。
From是拿出的意思,是直接scipy数据库拿出小工具(数据处理stats中拿出t检验(两组)和方差分析(多组)),代码可以直接写小工具的名字,比如stats.ttest_ind(第6、7行)
第8-9行:查找特定文件夹的特定文件格式(比如查找当前py文档所在文件夹的.xlsx格式的文件) ——这行存在的意义就是不用在换电脑时更换py代码中的数据文件位置
第10行,创建时间戳文件;
第11-12行:阻止烦人的提示(比如该代码能运行,却弹出提醒说以后可能不能用了)
备注:1.2.1 Agg是一种不显示图形界面、只把图画到文件里的后端。要求Matplotlib保存图片即可,不要弹窗(弹窗在网不好的时候会跳不出来,代码运行不下去)
1.2.2 ttest_ind独立样本 t 检验(比较两组数据有没有明显差异);
1.2.3 f_oneway:单因素方差分析(比较两组以上数据有没有明显差异);
1.2.4 pairwise_tukeyhsd:进阶统计(多重比较),记得安装这个工具包<pip install statsmodels>
# ========== 设置中文显示 ==========plt.rcParams['font.sans-serif'] = ['Microsoft YaHei', 'SimHei', 'Arial Unicode MS']plt.rcParams['axes.unicode_minus'] = False
为了解决Matplotlib 画图时的中文乱码问题
第1行设置字体(font),黑体/微软雅黑;第2行负数不会报错
二、获取数据文件
2.1获取数据文件所在的位置
# ========== 1. 自动获取当前脚本所在文件夹 ==========script_dir = os.path.dirname(os.path.abspath(__file__))output_dir = script_dirprint("=" * 70)print("Excel 数据分析工具")print("=" * 70)print(f"\n脚本所在文件夹:{script_dir}")
自动找到当前脚本所在的文件夹,会在终端运行时展示,如图:2.1.1 script_dir:找到脚本所在的位置(提取绝对路径,去掉代码名称,只保留文件夹的位置)2.1.2 os 是 Python 自带的"操作系统工具包",让你用代码来操作文件和文件夹,不需要手动去点鼠标
2.2 代码案例深度学习:获取数据文件
# ========== 2. 自动查找该文件夹下的所有Excel文件 ==========excel_files = glob.glob(os.path.join(script_dir, "*.xlsx")) + \ glob.glob(os.path.join(script_dir, "*.xls"))if len(excel_files) == 0: print(f"\n错误:在 {script_dir} 中没有找到任何Excel文件!") print("请将Excel文件放在与脚本相同的文件夹下,然后重新运行。") input("\n按 Enter 键退出...") exit()elif len(excel_files) == 1: file_path = excel_files[0] print(f"\n自动找到Excel文件:{os.path.basename(file_path)}")else: print(f"\n找到 {len(excel_files)} 个Excel文件:") for i, f in enumerate(excel_files, 1): print(f" {i}. {os.path.basename(f)}") choice = input(f"\n请选择文件序号(1-{len(excel_files)},直接回车默认选1): ").strip() if choice.isdigit() and 1 <= int(choice) <= len(excel_files): file_path = excel_files[int(choice) - 1] else: file_path = excel_files[0] print(f"\n已选择:{os.path.basename(file_path)}")
列出该文件夹下所有的 Excel 文件,下述是可能出现的问题:第一:如果没有符合要求的文件,会提示重新放置再次运行;第三:如果有多个文件,按照123..的顺序排序,用户在终端输入数字,即可选择该文件进行分析2.2.1 glob.glob:"通配符文件匹配",即去电脑里找符合这个规则的文件。第一个glob是模块,第二个glob是函数:
①*.xlsx:以xlsx扩展名的所有文件
②?.xlsx:单个字符的以xlsx扩展名的所有文件,比如2.xlsx或者a.xlsx
③[0-9]*.xlsx:查找数字开头的文件
2.2.2 if...elif...else:对超过两个条件做归类。这个语法有效避免了多层if else的语句,层级深,代码长的问题。
2.2.3 else:当存在多个数据文件时,列出待选择;
f:文件的完整路径;
enumerate:遍历列表,从1开始编号,i代表序号1,2,3...;
输出:文件的完整路径+序号+数据文件的名称
手动输入序号(符合要求),计算机会处理到所需文件,否则均默认按照看到的第一个文件处理
2.3:定位文件信息(列、行条件)
# ========== 4. 自动检测列名(智能匹配) ==========print(f"\n正在读取数据...")df = pd.read_excel(file_path)# 尝试常见的中英文列名common_group_names = ['分组', '组别', '处理', 'group', 'Group', '处理组', '组', 'GroupName']common_value_names = ['数值', '值', '表达量', '浓度', 'value', 'Value', '表达', 'measurement']def find_column(possible_names, df_columns): for name in possible_names: if name in df_columns: return name return Nonegroup_col = find_column(common_group_names, df.columns)value_col = find_column(common_value_names, df.columns)if group_col is None or value_col is None: print("\n未能自动识别列名,请手动输入:") if group_col is None: group_col = input("请输入分组列名(如:分组、组别、处理): ").strip() if value_col is None: value_col = input("请输入数值列名(如:数值、浓度、表达量): ").strip() # 再次验证 if group_col not in df.columns or value_col not in df.columns: print(f"\n列名错误!将使用前两列作为数据。") group_col = df.columns[0] value_col = df.columns[1]else: print(f"\n自动识别列名:分组列 = '{group_col}',数值列 = '{value_col}'")
上述代码意义:①开始②查找常见列名③找到了——显示自动识别成功;找不到,手动输入④手动输入正确,进行分析;手动输入错误,默认使用前两列进行分析,如下图展示
上述有个更好的办法,将30行代码缩略为3行:固定文件格式,无需手动输入操作,无需筛查
2.4 可选:更改代码,定位文件信息(文件格式固定的情况下)
# ========== 4. 直接指定列名 ==========group_col = '分组' # 固定列名value_col = '数值' # 固定列名
# ========== 5. 数据清洗 ==========df_clean = df[[group_col, value_col]].dropna()groups = df_clean[group_col].unique()print(f"\n共有 {len(groups)} 组:{list(groups)}")
df:原始数据表;[[group_col, value_col]]:从原始表中提取两列(分组列和数值列);.dropna():删除这两列中有任何空值的行unique():找出不同的分组。第4行输出共有几组,组的list,如下
以上只完成数据查找和清洗的代码学习,下篇将学习数据对比分析的代码
关注我,一起学习呀~