前言:
由于大数据时代的来临,数据分析技术将帮助企业用户在合理时间内获取、管理、处理以及整理海量数据,为企业经营决策提供积极的帮助。数据分析作为一门前沿技术,广泛应用于物网、云计算、移动互联网等战略性新兴领域。虽然大数据技术目前在国内还处于发展的初级阶段,但是其商业价值已经显现出来,有实践经验的数据分析人才更是各企业争夺的热门。为了满足日益增长的数据分析人才需求,很多高校开始尝试开设不同难度的数据分析课程。“数据分析”作为大数据时代的核心技术,有望成为高校大数据相关专业的重要课程之一。
一、数据分析概述:
1.1数据分析概念
数据分析通常是指用适当的分析方法对收集来的大量数据进行分析,提取有用信息并形成结论,对数据加以详细研究和概括总结的过程。随着计算机技术的全面发展,企业生产、收集、存储和处理数据的能力大大提高,数据量与日俱增。而在现实生活中,需要对这些繁多、复杂的数据通过统计分析进行提炼,以此研究出数据的发展规律,进而帮助企业管理层做出决策 。
广义数据分析是指依据一定的目标,通过统计分析、聚类、分类等方法发现大量数据 步中的目标所隐含信息的过程。广义数据分析包括狭义数据分析和数据挖掘。狭义数据分析是指根据分析目的,采用对比分析、分组分析、交叉分析和回归分析等分析方法,对收集的数据进行处理与分析,提取有价值的信息,发挥数据的作用,得到一个特征统计量结果的过程。数据挖掘则是指从大量的、不完全的、有噪声的、模糊的、随机的实际应用数据中,通过应用智能推荐、关联规则、分类模型和聚类模型等技术,挖掘信息潜在价值的过程。广义数据分析的概念如图1-1所示。
1.2数据分析的流程
数据分析已经逐渐演化为一种解决问题的过程,甚至是一种方法论。虽然每个公司都会根据自身需求和目标创建最适合的数据分析流程,但是数据分析的核心步骤是一致的。图1-2是一个典型的数据分析流程。
二、Python数据分析的工具
Python的强大,在于其背后丰富的库生态系统。数据分析离不开这些核心工具
-
数据处理基石:Pandas
-
核心:
DataFrame
和Series
数据结构,如同强大的电子表格。 -
功能: 数据加载(CSV, Excel, SQL, JSON等)、清洗(处理缺失值、异常值、重复值)、转换(合并、重塑、分组聚合)、探索性分析。
-
代码示例:
import pandas as pd # 读取数据 data = pd.read_csv('sales_data.csv') # 查看前5行 print(data.head()) # 处理缺失值 - 用均值填充某列 data['price'].fillna(data['price'].mean(), inplace=True) # 分组聚合 - 按地区计算平均销售额 region_sales = data.groupby('region')['sales'].mean() print(region_sales)
-
-
科学计算基础:NumPy
-
核心: 高效的多维数组 (
ndarray
) 对象和数学函数库。 -
作用: 为Pandas等库提供底层高性能数组运算支持(向量化操作),处理数值计算、线性代数、随机数生成等。
-
代码示例:
import numpy as np # 创建数组 arr = np.array([1, 2, 3, 4]) # 向量化运算 - 每个元素平方 squared = arr ** 2 print(squared) # 输出: [1 4 9 16]
-
-
数据可视化利器:Matplotlib & Seaborn
-
Matplotlib: 基础且灵活的绘图库,提供高度定制化能力。
-
Seaborn: 基于Matplotlib的高级接口,专注于统计图形绘制,默认样式美观,简化了复杂图表的创建(如热力图、箱线图、小提琴图、分布图、回归图)。
-
代码示例 (Seaborn 箱线图):
import seaborn as sns import matplotlib.pyplot as plt # 加载示例数据集 tips = sns.load_dataset('tips') # 绘制箱线图:不同天的账单分布 sns.boxplot(x='day', y='total_bill', data=tips) plt.title('Distribution of Total Bill by Day') plt.show()
-
-
统计建模与机器学习:SciPy & Scikit-learn
-
SciPy: 建立在NumPy之上,提供科学计算中的高级模块(优化、积分、插值、信号处理、统计函数等)。
-
Scikit-learn (
sklearn
): 机器学习领域的标杆库。提供:-
统一且简洁的API (
fit
,predict
,transform
)。 -
丰富的算法:分类、回归、聚类、降维、模型选择、预处理。
-
完善的工具:数据分割、交叉验证、评估指标。
-
-
代码示例 (Scikit-learn 线性回归):
from sklearn.model_selection import train_test_split from sklearn.linear_model import LinearRegression from sklearn.metrics import mean_squared_error # 假设 X 是特征, y 是目标变量 (已准备好) X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) # 创建并训练模型 model = LinearRegression() model.fit(X_train, y_train) # 预测 y_pred = model.predict(X_test) # 评估 mse = mean_squared_error(y_test, y_pred) print(f'Mean Squared Error: {mse:.2f}')
-
-
交互式利器:Jupyter Notebook/Lab
-
作用: 交互式开发环境,将代码、可视化、解释性文本(Markdown)整合在一个文档中。
-
优势: 非常适合数据分析的探索性、迭代式工作流程,便于展示和分享分析过程和结果。
-
三、Python的Anaconda发行版
Python 拥有 NumPy、SciPy、pandas、Matplotlib、seaborn、pyecharts 和scikit-learn等功能齐全、接口统一的库,能为数据分析工作提供极大的便利。不过库的管理和版本问题,使得数据分析人员并不能够专注于数据分析,而要将大量的时间花费在与环境配置相关的问题上。基于这个情况,Anaconda发行版应运而生。
安装教程
四、Jupyter Notebook常用功能
Jupyter Notebook (此前被称为IPython Notebook)是一个交互式笔记本,支持运行40多种编程语言,本质上是一个支持实时代码、数学方程、可视化和Markdown 的Web 应用程序。对于数据分析,Jupyter Notebook的优点是可以重现整个分析过程,并将说明文字、代码、图表、公式和结论都整合在一个文档中。用户可以通过电子邮件、Dropbox、GitHub 和Jupyter Notebook Viewer将分析结果分享给其他人。
五、 Python数据分析的应用
1.pandas统计分析基础
(一)核心数据结构:理解分析对象
-
Series
:-
一维带标签数组,类似加强版的列表或字典。
-
核心组成部分:
index
(索引/标签) +values
(值数组)。 -
创建:
s = pd.Series([1, 3, 5, np.nan, 6], index=['a', 'b', 'c', 'd', 'e'])
-
-
DataFrame
:-
二维表格型数据结构,是统计分析的核心对象。
-
可看作多个共享相同索引的
Series
的集合(列)。 -
核心组成部分:
index
(行索引) +columns
(列名) +values
(二维数据值)。 -
创建:
df = pd.DataFrame({'A': [1, 2, 3], 'B': ['a', 'b', 'c'], 'C': pd.Timestamp('20230101')})
-
(二) 数据加载与预览
-
加载数据:
# 从 CSV
df = pd.read_csv('data.csv')
# 从 Excel
df = pd.read_excel('data.xlsx', sheet_name='Sheet1')
# 从 SQL (需要 SQLAlchemy 引擎)
import sqlalchemy
engine = sqlalchemy.create_engine('sqlite:///mydatabase.db')
df = pd.read_sql('SELECT * FROM mytable', engine)
2.数据预览:
df.head(n=5) # 查看前 n 行 (默认 5)
df.tail(n=3) # 查看后 n 行 (默认 5)
df.sample(n=2) # 随机查看 n 行
df.shape # 返回 (行数, 列数) 元组
df.columns # 查看列名列表
df.index # 查看索引信息
df.dtypes # 查看每列的数据类型
df.info() # 综合信息:索引范围、列名、非空计数、数据类型
2.创建DataFrame
主要使用 Pandas的 DataFrame()方法
#通过字典形式创建 DF
import pandas as pd
#解决数据输出时,列名不对齐的问题
pd.set_option('display.unicode.east_asian_width', True)
df = pd.DataFrame({
'语文': [110,105,99],
'数学': [105,88,115],
'英语': [109,120,130],
'班级':'2024人工智能1班'
}, index=[0,1,2])
print(df)
代码结果如下:
3.导入外部数据
主要使用 Pandas的 read_excel()方法,例如要导入“1月.xlsx”的表格内容。
# 1. 常规导入
import pandas as pd
df = pd.read_excel('1月.xlsx')
# print(df) # 输出表格全部的数据
print(df.head(10)) # 输出表格前5行的数据
代码结果如下:
指定导入内容:
# 1. 导入指定 Sheet页 的内容
import pandas as pd
# df = pd.read_excel('1月.xlsx' ,sheet_name = '莫寒')
#除了指定Sheet页的名字外,还可以指定Sheet页的顺序,从0开始,例如'莫寒'工作表的 sheet_name = 1,表示导入第二个sheet页的数据。
df = pd.read_excel('1月.xlsx' ,sheet_name = 1)
print(df.head(5)) # 输出表格前5行的数据
代码结果如下:
DF是二维数据结构,因此它既有行索引也有列索引。当导入Excel数据时,行索引会自动生成,如0,1,2;而列索引则默认第0行作为列索引,如A,B,C,D
# 该例子将通过指定列索引导入Excel数据,需要设置 header参数。
# 设置第一行为列索引
import pandas as pd
#将Excel表格的第 1 行作为列索引
df = pd.read_excel('1月.xlsx' ,sheet_name = 0, header= 1)
print(df.head(5)) # 输出表格前5行的数据
代码结果如下:
4.数据的抽取
# 一、抽取行
import pandas as pd
#解决数据输出时列名不对齐的问题
pd.set_option('display.unicode.east_asian_width', True)
data = [[110,105,99],[105,88,115],[109,120,130],[112,115,119]]
name = ['张丽','刘柳','高圆','黄芬']
columns = ['语文','数学','英语']
df = pd.DataFrame(data=data, index=name, columns=columns)
print(df)
print('1------------------------------------------')
# 1.抽取一行数据:抽取一行名为'刘柳' 的考试成绩数据
# loc属性:以列名(columns)和行名(index)作为参数。当只有一个参数的时候,默认是行名。即抽取整行数据,包括所有列。
df1=df.loc['刘柳']
print(df1)
print('2------------------------------------------')
# 2. loc属性有两个参数时:例如,抽取一行名为'刘柳' 的考试的数学成绩数据
df2=df.loc['刘柳', '数学']
print(df2)
print('3------------------------------------------')
# 3. loc属性:抽取所有行,列名为'英语' 的考试成绩数据,此时所有行,用冒号代替。
df3=df.loc[ : , '英语']
print(df3)
print('4------------------------------------------')
# 4. loc属性:抽取任意多行数据。例如抽取行名为 “张丽 ” 和 “ 高圆 ” 的成绩
# 注意,是两个中括号,并且中间是逗号,不是分号。思考下,为什么是两个中括号?因为写成列表后才表示['张丽', '高圆']整体为 loc属性的第一个参数。
# df4=df.loc[ ['张丽', '高圆'] ]
df4=df.iloc[[0,2]]
print(df4)
print('5------------------------------------------')
# 5. loc属性:抽取任意多行连续的数据。例如抽取 “刘柳 ” 到 “ 黄芬 ” 的成绩。
# 注意,是一个中括号,并且中间是分号,分号是表示切片。切片也是表示连续的意思。 包头包尾
# df5=df.loc['刘柳':'黄芬']
df5=df.iloc[1:4] # 刘柳是第 2行,索引是 1。黄芬是第 4行,索引是 3。说明 iloc()抽取连续多行数据时,包头不包尾。
print(df5)
print('6------------------------------------------')
# 6. loc属性:抽取任意多行连续的数据的【特例】,抽取数据从第一行开始, 到 “ 高圆 ” 的成绩。
# 注意区分一下,和第三点相比,中间少了个逗号。
df6=df.loc[: '高圆' ]
print(df6)
print('7------------------------------------------')
# 7.从第2行开始,取到最后一行数据。
df7 = df.iloc[1: : ] # 第 2行,索引是 1。中间的冒号是切片的语法,最后一个冒号表示到最后的意思。
print(df7)
代码结果如下:
5.数据的增加、修改、删除
(一)数据的增加:
# 1. 按列增加数据。可以用以下三种方法实现。
import pandas as pd
#解决数据输出时列名不对齐的问题
pd.set_option('display.unicode.east_asian_width', True)
data = [[110,105,99],[105,88,115],[109,120,130],[112,115,119]]
name = ['张丽','刘柳','高圆','黄芬']
columns = ['语文','数学','英语']
df = pd.DataFrame(data=data, index=name, columns=columns)
print(df)
print('1------------------------------------------')
# 在最后一列,增加一列 “物理” 成绩。
# (1)直接为 DataFrame对象赋值。
df['物理'] = [88,93,52,59]
print(df)
print('2------------------------------------------')
# (2)使用loc()属性,在最后一列,增加一列 “物理” 成绩。
df.loc[: , '物理'] = [88,93,52,59] # 冒号表示所有行,'物理'表示增加的列名。
print(df)
print('3------------------------------------------')
# 在指定位置插入一列数据,用 insert()方法。
# 在第 1 列后面插入一列 '物理' 成绩。
df.insert(1, '物理', [88,93,52,59], allow_duplicates = True) # allow_duplicates = True是允许列重复。
print(df)
代码结果如下:
(二)数据的修改:
import pandas as pd
#解决数据输出时列名不对齐的问题
pd.set_option('display.unicode.east_asian_width', True)
data = [[110,105,99],[105,88,115],[109,120,130],[112,115,119]]
name = ['张丽','刘柳','高圆','黄芬']
columns = ['语文','数学','英语']
df = pd.DataFrame(data=data, index=name, columns=columns)
print(df)
print('1------------------------------------------')
# 1.修改列的标题
# (1)将列名‘数学’修改为‘数学(上册)’
# 使用DataFrame的 columns属性,然后直接赋值即可。
df.columns = ['语文','数学(上册)','英语'] # 虽然只修改第二列的列名,但是其余列的列名也是要写上。否则会报错。
print(df)
print('2------------------------------------------')
#(2)另外一种方法,使用 DataFrame的rename()方法修改列标题。
df.rename(columns = {'语文':'语文(上)', '数学':'数学(上册)', '英语': '英语(上)'}, inplace=True) # inplace=True表示直接修改 df 。
print(df)
print('3------------------------------------------')
# 2.修改行的标题
# (1)使用DataFrame的 index 属性,然后直接赋值即可。
# 将行标题统一修改为数字编号:
df.index = list('1234') # 将DataFrame的索引设置为列表['1', '2', '3', '4']。这里需要注意的是,list('1234')会将字符串中的每个字符拆分成列表项,
# 所以生成的列表是四个元素,每个字符一个
print(df)
print('4------------------------------------------')
# (2)使用DataFrame的 rename 属性也可以修改行标题。例如将行标题统一修改为数字编号:
df.rename({'张丽':1, '刘柳':2 ,'高圆':3, '黄芬':4 }, axis = 0, inplace=True) # 指定 axis = 0,也就是行索引。
print(df)
代码结果如下:
(三)数据的删除:
# 使用 DataFrame 对象的 drop()方法,它的参数说明如下:
# labels:表示行标签或列标签
# axis:axis = 0,表示按行删除; axis = 1,表示按列删除; 若 axis 的值没有给出,那么默认等于0,也就是按行删除。
# index:删除行,默认值为 None
# columns :删除列,默认值为 None
# inplace:是可选参数,对原数组做出修改,并返回一个新的数组。默认值为 False,如果值为 True,那么原数组直接被替换。
import pandas as pd
#解决数据输出时列名不对齐的问题
pd.set_option('display.unicode.east_asian_width', True)
data = [[110,105,99,99],[105,88,115,99],[109,120,130,99],[112,115,119,99]]
name = ['张丽','刘柳','高圆','黄芬']
columns = ['语文','数学','英语','物理']
df = pd.DataFrame(data=data, index=name, columns=columns)
print(df)
# 删除列
print('6------------------------------------------')
# (1)删除 '数学' 列的数据。方法一
# df.drop(['数学'] , axis = 1, inplace = True) # inplace = True, 原数组直接被替换
# print(df)
df1 = df.drop(['数学'] , axis = 1, inplace = False) # inplace = False, 原数组没有被替换。只是删除了数学这一列,然后重新生成一个新的数组。
print(df1)
print(df)
print('7------------------------------------------')
# (2)删除 '英语' 列的数据。方法二
df.drop(columns = '英语' , axis = 1, inplace = True)
print(df)
print('8------------------------------------------')
# (3)删除 列标签为'语文' 的列数据。方法三
df.drop(labels= '语文' ,axis = 1, inplace = True)
print(df)
代码结果如下:
6.重新设置索引
# 重新设置索引
# reindex() 函数。它的作用是创建一个适合新索引的新对象。
# (1)对 Series对象重新设置索引
import pandas as pd
s1 = pd.Series([88,60,75] , index=[1,2,3] )
print(s1)
s2 = s1.reindex([1,2,3,4,5])
print(s2)
# (2)对 DataFrame对象重新设置索引
d = [[102,56,89],[88,62,32],[55,37,98]]
i = ['m1','m2','m3']
c = ['语文','数学','英语']
df = pd.DataFrame(data = d, index = i, columns = c)
print(df)
# 用 reindex()方法重新设置行索引
df1 = df.reindex(['m1','m2','m3','m4','m5'])
print(df1)
# 用 reindex()方法重新设列索引
df2 = df.reindex(columns = ['语文','物理','数学','英语'])
print(df2)
# 用 reindex()方法重新设行索引和列索引
df3 = df.reindex(['m1','m2','m3','m4','m5'], columns = ['语文','物理','数学','英语'])
print(df3)
代码结果如下:
7.数据排名
排名是根据 Series 对象或者 DataFrame 对象的某几列的值进行排名的。
主要使用 rank()方法,该函数参数:
(1)axis 如果axis=0 表示行; 如果axis=1 表示列。默认值是0 ,对行排序。
(2)method 参数控制如何处理平级关系(也就是在相同值的时候,所使用的排序方法)。它可以接受以下几个值:
‘average’(默认)平均排名。
‘first’:按值在原始数据中的出现顺序分配排名。
‘min’:使用最小值排名。
‘max’:使用最大值排名。
‘dense’:密集排名。类似于’min’最小值排名。但是排名中每次只增加 1,即排名相同的数据只占一个名次。
(3)ascending: 等于True 则升序。等于False 则降序。如果指定多个排序,那么可以使用布尔值列表。默认为 False。
(4)numeric_only: 如果你的DataFrame包含非数值列(如字符串或日期),并且你只想对数值列进行排名,可以设置numeric_only = True。
(5) na_option: 是空值的排序方法。默认情况下,rank()方法将 NaN 值视为最大的值(即它们将获得最大的排名)。
如果你想改变这种行为(例如,将 NaN 值视为最小的值或忽略它们),可以使用na_option参数。该参数接受以下几个值:
‘keep’(默认):保留 NaN 值,并将它们视为 最大 的值。
‘top’:将 NaN 值视为 最小 的值。
‘bottom’:将 NaN 值视为最大的值(与默认行为相同)。如果按照升序排序,那么将最大排名赋给 NaN。
(6)pct: 是布尔值,是否以百分比的形式显示返回的排名。默认为 False。
8.绘制图形
(一)绘制饼图:
主要用于展示各部分数据占总体的比例关系
函数语法; plt.pie(x, explode=None, labels=None, colors=None, autopct=None, **kwargs, radius = 1)
x:表示各部分的数据值,是绘制饼图的核心数据。
explode:用于突出显示某些部分,是一个与 x 长度相同的数组,值越大,对应的部分突出越明显。
labels:各部分的标签,方便我们识别每个扇形代表的内容。
colors:各部分的颜色,可自定义以增加图表的美观度。
autopct:用于显示各部分所占百分比的格式,
如 '%1.1f%%' 表示保留一位小数。
radius: 半径,默认值是1
import matplotlib.pyplot as plt
labels = ['娱乐', '育儿', '饮食', '房贷', '交通', '其它']
x = [200, 500, 1200, 7000, 200, 900]
# 绘制饼图
plt.pie(x, labels=labels, autopct='%1.1f%%')
# 设置图表标题
plt.title("家庭支出比例")
# 显示图表
plt.show()
代码结果如下:
# 代码 05-19
import pandas as pd
from matplotlib import pyplot as plt
df1 = pd.read_excel('data2.xlsx')
plt.rcParams['font.sans-serif']=['SimHei'] #解决中文乱码
plt.figure(figsize=(5,3)) #设置画布大小
labels = df1['地区']
sizes = df1['销量']
#设置饼形图每块的颜色
colors = ['red', 'yellow', 'slateblue', 'green','magenta','cyan','darkorange','lawngreen','pink','gold']
# 分裂饼图参数:explode
explode = (0.1, 0,0,0,0,0,0,0,0,0)
plt.pie(sizes, #绘图数据
labels=labels,#添加区域水平标签
colors=colors,# 设置饼图的自定义填充色
labeldistance=1.02,#设置各扇形标签(图例)与圆心的距离
autopct='%.1f%%',# 设置百分比的格式,这里保留一位小数
startangle=90,# 设置饼图的初始角度
radius = 0.5, # 设置饼图的半径
center = (0.2,0.2), # 设置饼图的原点
textprops = {'fontsize':9, 'color':'k'}, # 设置文本标签的属性值
pctdistance=0.6, # 设置百分比标签与圆心的距离
explode=explode, #分裂饼图
shadow=True # 立体感带阴影饼图
)
# 设置x,y轴刻度一致,保证饼图为圆形
plt.axis('equal')
plt.title('2020年1月各地区销量占比情况分析')
代码结果如下:
(二)内嵌环形饼图:
import pandas as pd
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['SimHei']
df1 = pd.read_excel('data2.xlsx')
df2=pd.read_excel('data2.xlsx',sheet_name='2月')
#数据集,x1,x2分别对应外环、内环百分比例
x1=df1['销量']
x2=df2['销量']
#设置饼状图各个区块的颜色
colors = ['red', 'yellow', 'slateblue', 'green','magenta','cyan','darkorange','lawngreen','pink','gold']
#外环
plt.pie(x1,autopct='%.1f%%',radius=1,pctdistance=0.85,colors=colors,wedgeprops=dict(linewidth=2,width=0.3,edgecolor='w'))
#内环
plt.pie(x2,autopct='%.1f%%',radius=0.7,pctdistance=0.7,colors=colors,wedgeprops=dict(linewidth=2,width=0.4,edgecolor='w'))
#图例
legend_text=df1['地区']
plt.legend(legend_text,title='地区',frameon=False,bbox_to_anchor=(0.2,0.5))#设置图例标题、位置、去掉图例边框
plt.axis('equal')#设置坐标轴比例以显示为圆形
plt.title('2020年1月和2月各地区销量占比情况分析')
plt.show()
代码结果如下:
(三)标准面积图
import pandas as pd
import matplotlib.pyplot as plt
df = pd.read_excel('books.xlsx')
plt.rcParams['font.sans-serif']=['SimHei'] #解决中文乱码
x=df['年份']
y=df['销售额']
#图表标题
plt.title('2013-2019年线上图书销售情况')
plt.stackplot(x, y)
# 强制将y轴的刻度标签显示为普通数字格式(而非科学计数法)。当数据值较大时(如超过1e5),Matplotlib默认会使用科学计数法显示,
plt.ticklabel_format(axis='y', style='plain')
plt.show()
代码结果如下:
总结:
Python数据分析不仅仅是一门技术,更是一种从数据中提取价值、驱动决策的思维方式。它为我们提供了一套强大的工具链,让我们能够高效地处理海量数据、发现隐藏模式、预测未来趋势并解决实际问题。无论你是业务分析师、数据科学家、工程师还是任何对数据感兴趣的人,掌握Python数据分析都将成为你在这个数据驱动时代的一项核心竞争力。立即开始你的Python数据分析之旅,探索数据的无限可能吧!