【Python数据分析】数据分析完整流程(全)

目录

[一、 数据分析流程](#一、 数据分析流程)

[1. 数据的导入(pd.read_csv(【文件名】)) 和 导出(pd.to_csv(【文件名】))](#1. 数据的导入(pd.read_csv(【文件名】)) 和 导出(pd.to_csv(【文件名】)))

[2. json 数据的读取](#2. json 数据的读取)

[3. 缺失值的处理](#3. 缺失值的处理)

[4. 剔除缺失值](#4. 剔除缺失值)

[5. 填充缺失值](#5. 填充缺失值)

[6. 数据类型转换](#6. 数据类型转换)

[7. 数据变形](#7. 数据变形)

[8. 数据分列](#8. 数据分列)

[9. 数据分箱](#9. 数据分箱)

[10. 时间数据的处理](#10. 时间数据的处理)

[11. 分组聚合](#11. 分组聚合)

案例分析

企鹅数据分析

睡眠质量分析

[总结不易~ 本章节对我有很大的收获, 希望对你也是!!!](#总结不易~ 本章节对我有很大的收获, 希望对你也是!!!)


本节素材已上传至Gitee:https://gitee.com/liu-yihao-hhh/learning-python/commit/4eb5c54de0ca3e26c3c22befed74ac30df901b86https://gitee.com/liu-yihao-hhh/learning-python/commit/4eb5c54de0ca3e26c3c22befed74ac30df901b86

一、 数据分析流程

1. 数据的导入(pd.read_csv(【文件名】)) 和 导出(pd.to_csv(【文件名】))

2. json 数据的读取

python 复制代码
# json数据
df = pd.read_csv('data/data1.json')
print(df, type(df))
df

如果json数据 读取有问题 那么就先将json文件数据读入字典里 再重新用pd.DataFrame 来进行读出

import json
with open('data/test.json') as f:
    data = json.load(f) # json.load 将json文件数据 先读到字典里

print(data)
print(type(data))
df = pd.DataFrame(data['users'])
df

3. 缺失值的处理

python 复制代码
# 缺失值的处理
import numpy as np
import pandas as pd
import json

s = pd.Series([1, 2, np.nan, None, pd.NA])
# print(s)
# 监测 是否是缺失值
# print(s.isna())
# print(s.isnull())
df = pd.DataFrame([[1, pd.NA, 2], [2, 3, 5], [None, 4, 6]])
df
# print(df.isna()) # 查看是否是缺失值
print(df.isna().sum(axis=1)) # 查看缺失值的个数 默认表示的是列索引 在sum内axis=1 表示计算行缺失值的个数
print(s.isna().sum())

4. 剔除缺失值

python 复制代码
# 剔除缺失值
print(s.dropna())
print(df)
print('-'*30)
print(df.dropna()) # 只要该行有缺失值 就直接删除一行
print('-'*30)
print(df.dropna(how='all')) # 如果所有的值都是缺失值 删除这一行
print('-'*30)
print(df.dropna(thresh=2)) # 如果至少有n个值不是缺失值 就保留
print('-'*30)
print('@',df.dropna(subset=[1])) # 如果某列有缺失值 则删除这一行

5. 填充缺失值

python 复制代码
# 缺失值的填充
df = pd.read_csv('data/weather_withna.csv')
df.tail()
df.isna().sum()
df.head()
# 使用字典来填充
print(df.fillna({'temp_max':20, 'wind': 2.5}))
print(df.fillna(df[['wind']].mean()).tail()) # 使用统计值来填充

print(df.ffill().tail()) # 使用前面的值来进行填充
print(df.bfill().tail()) # 使用后面的值来进行填充

6. 数据类型转换

python 复制代码
import pandas as pd
data = {
    "name":["alice",'alice','bob','alice','jack','bob'],
    "age":[26,25,30,25,35,30],
    "city":['NY','NY','LA','NY','SF','LA']
}

df = pd.DataFrame(data)
df
python 复制代码
df.duplicated() # 一整条记录都是一样的 才会标记成重复 true
df.drop_duplicates(subset=['name']) # 去重
df.drop_duplicates(subset=['name'], keep='last') # keep 保留最后一次出现的行
python 复制代码
# 数据类型的转换
df = pd.read_csv('data/sleep.csv')
df.dtypes
python 复制代码
df['age'] = df['age'].astype('int16')
df.dtypes
python 复制代码
df['gender'] = df['gender'].astype('category') # 分类 类型 category
df.dtypes
python 复制代码
df['is_male'] = df['gender'].map({'Female':True, 'Male':False})
df.is_male

7. 数据变形

参数名 作用(通俗解释) 对应原数据的部分 举例(你的代码)
var_name 给「原列名」整合后的列起名字 原宽表的列名(如 Math) var_name='科目' → 生成「科目」列,存 Math/English 等
value_name 给「原列值」整合后的列起名字 原宽表的单元格值(如 90) value_name='分数' → 生成「分数」列,存 90/85 等
python 复制代码
#数据变形
import pandas as pd
data = {
    'ID': [1, 2],
    'name':['alice','bob'],
    'Math': [90, 85],
    'English': [88, 92],
    'Science': [95, 89]
}
df = pd.DataFrame(data)
df

宽表转长表

python 复制代码
df.T # 行列转置
df

# 1 alich math 90
# 1 alich english 88
# 1 alich science 95

# 宽表转换成 长表
df2 = pd.melt(df, id_vars=['ID', 'name'], var_name='科目', value_name='分数')
df2.sort_values('name')

长表转宽表

python 复制代码
# 长表转宽表
pd.pivot(df2, index=['ID', 'name'], columns='科目', values='分数')

8. 数据分列

python 复制代码
data = {
    'ID': [1, 2],
    'name':['alice smith','bob smith'],
    'Math': [90, 85],
    'English': [88, 92],
    'Science': [95, 89]
}
df = pd.DataFrame(data)
# 分列
df[['first', 'last']] = df['name'].str.split(" ",expand=True) # expand=True 就是多列的意思
df
python 复制代码
df = pd.read_csv('data/sleep.csv')
df = df[['person_id', 'blood_pressure']]
df[['high', 'low']] = df['blood_pressure'].str.split('/', expand=True) # 当前还是字符形式
df['high'] = df['high'].astype('int64')
df['low'] = df['low'].astype('int64')
df.info()

9. 数据分箱

python 复制代码
# 数据分箱 pd.cut(x, bins, labels)
import pandas as pd

df = pd.read_csv('data/employees.csv')
df.head(10)
python 复制代码
df1 = df.head(10)[['employee_id', 'salary']]
df1
python 复制代码
# bins 分段 bins=2 分成两端 起始值和结束值的中位数
pd.cut(df1['salary'], bins=2)
python 复制代码
pd.cut(df1['salary'], bins=2).value_counts() # 计算每段的人数总数
python 复制代码
pd.cut(df1['salary'], bins=[0, 10000, 20000, 30000]).value_counts() # bins 也可以自定义分段
python 复制代码
# labels 对范围进行标记
df1['收入范围'] = pd.cut(df1['salary'], bins=[0, 10000, 20000, 30000], labels=['低', '中', '高'])
df1
python 复制代码
# qcut 进行等频率划分
pd.qcut(df1['salary'], 3).value_counts()
python 复制代码
# 睡眠数据
df = pd.read_csv('data/sleep.csv')
df1 = df.head(10)[['person_id', 'sleep_quality']]
df1
python 复制代码
df['睡眠质量'] = pd.cut(df['sleep_quality'], bins=3, labels=['差', '中', '优'])
print(df1)
print(df['睡眠质量'].value_counts())
df['gender'] = df['gender'].astype('category')
print(df['gender'].value_counts())

数据分箱的目的

python 复制代码
# 分箱的目的 就是为了要把数值 给转换成类别 然后进行统计
# 字符串 -> 类别 -> 统计
# 数值 -> 分箱 -> 统计
print(df['gender'].dtype)
print(df['睡眠质量'].dtype)
python 复制代码
# df.rename() df.set_index() df.reset_index()
df = pd.DataFrame({
    'name':['jack', 'alice', 'tom', 'bob'],
    'age':[20, 30, 40, 50],
    'gender':['female', 'male', 'female', 'male'],
})
# 直接设置索引 设置索引为name这一列 inplace=True 进行固定
df.set_index('name', inplace=True)
df
python 复制代码
# 设置索引为原来的状态
df.reset_index(inplace=True)
df
python 复制代码
# 修改列名(columns) 修改索引名(index)
df.rename(columns={'age':'年龄'}, index={0:4})
python 复制代码
df.index=[1, 2, 3, 4]
df.columns = ['姓名', '年龄', '性别']
df

10. 时间数据的处理

python 复制代码
# 时间数据的分析
import pandas as pd
d = pd.Timestamp('2015-05-02 10:22')
print(d)
print(type(d))
print('年:', d.year)
print('月:', d.month)
print('日:', d.day)
print(d.hour, d.minute, d.second)
print('季度', d.quarter)
print('是否是月底:', d.is_month_end)
python 复制代码
# 方法
print('星期几:', d.day_name)
print('转换为天:', d.to_period('D'))
print('转换为季度:', d.to_period('Q'))
print('转换为年度:', d.to_period('Y'))
print('转换为月度:', d.to_period('M'))
python 复制代码
# 字符串转换为日期类型
a = pd.to_datetime('2015-02-28 10:22')
print(a)
print(type(a))
print(a.day_name())

# dataframe 日期转换
df = pd.DataFrame({
    'sales': [100, 200, 300],
    'date': ['20250601', '20250602', '20250603']
})

# df['datetime'] 是「日期时间型 Series」,.dt 是 Pandas 专门为这类 Series 设计的「日期时间属性访问器」------ 只有通过 .dt,才能调用日期时间专属的方法 / 属性(比如年、月、星期名)。

df['datetime'] = pd.to_datetime(df['date'])
df['week'] = df['datetime'].dt.day_name()
df['datetime'].dt.year
python 复制代码
# csv 日期转换
df = pd.read_csv('data/weather.csv')
df['datetime'] = pd.to_datetime(df['date'])
df.info()
df['datetime'].dt.day_name()
python 复制代码
# csv 日期转换 parse_dates=[] 跟上面一行一样
df = pd.read_csv('data/weather.csv', parse_dates=['date'])
df.info()
df['date'].dt.day_name()
python 复制代码
# 日期数据作为索引
# 设置一次就生效了 不需要多次设置
# df.set_index('date', inplace=True) # 将原来的df设置为索引
print(df)
print(df.loc['2013-01':'2013-02'])
python 复制代码
# 时间间隔
d1 = pd.Timestamp('2013-01-15')
d2 = pd.Timestamp('2023-02-23')
d3 = d2 -d1
print(d3)
python 复制代码
df = pd.read_csv('data/weather.csv', parse_dates=['date'])
df.info()
df['delta'] = df['date'] - df['date'][0]
df.set_index('delta', inplace=True)
python 复制代码
df
print(df.loc['10 days' : '20 days'])
python 复制代码
days = pd.date_range('2025-07-03', '2026-02-09', freq='W') # W 隔一周
days = pd.date_range('2025-07-03', periods=10, freq='W') # W 隔一周
print(days)
python 复制代码
df = pd.read_csv('data/weather.csv', parse_dates=['date'])
# 重新采样
df.set_index('date', inplace=True)

df[['temp_max', 'temp_min']].resample('YE').mean()
python 复制代码
df[['temp_max', 'temp_min']].resample('YS').mean()

11. 分组聚合

分组聚合是 Pandas 最核心的数据分析功能之一,核心逻辑是「先分组、后聚合」------ 把数据按某个 / 某些字段分成若干组,再对每组数据计算统计值(比如平均值、求和、计数)。

  • 分组:把所有员工按「部门 ID」分开(比如部门 20 的放一堆、部门 30 的放另一堆);
  • 聚合:对每一堆(每个部门)计算「平均薪资」(比如部门 20 的平均薪资、部门 30 的平均薪资)。
python 复制代码
# 分组聚合
import pandas as pd
df = pd.read_csv('data/employees.csv')  # 读取员工数据
print(df['department_id'].isna().sum())  # 统计部门ID的缺失值数量(比如输出5,说明有5行没填部门ID)
df = df.dropna(subset=['department_id'])  # 删除部门ID为空的行(没部门的员工,没法按部门分组)
df['department_id'] = df['department_id'].astype('int64')  # 把部门ID转成整数(比如从字符串"20"变成数字20,方便分组)

# 查看所有分组:返回一个字典,键=分组值(部门ID),值=该组对应的行索引
df.groupby('department_id').groups  
# 示例输出:{10: [0,5], 20: [1,3,7], 30: [2,4,6]} → 部门10包含索引0、5的行,部门20包含1、3、7的行...

# 查看具体分组:提取部门ID=20的所有数据(相当于"只看部门20的员工表")
df.groupby('department_id').get_group(20)  

# 第一步:按部门分组,对salary列计算平均值
df2 = df.groupby('department_id')[['salary']].mean()
# 拆解这行的每一部分:
# - df.groupby('department_id') → 按部门ID分堆
# - [['salary']] → 只关注每堆的salary列(不关心其他列)
# - .mean() → 对每堆的salary列计算平均值
# 结果df2的结构:
#            salary
# department_id
# 10           5000.0
# 20           8000.0
# 30           6500.0
# 注意:此时department_id是"索引"(行名),不是普通列

# 第二步:把平均薪资保留2位小数(比如8000.123→8000.12)
df2['salary'] = df2['salary'].round(2)

# 第三步:重置索引(把部门ID从"索引"变回普通列,方便后续排序/查看)
df2.reset_index()
# 重置后结构:
#    department_id  salary
# 0             10  5000.00
# 1             20  8000.00
# 2             30  6500.00

# 第四步:按薪资从高到低排序(看哪个部门平均薪资最高)
df2.sort_values('salary', ascending=False)
# 排序后结果:
#    department_id  salary
# 1             20  8000.00
# 2             30  6500.00
# 0             10  5000.00
python 复制代码
# 计算不同岗位的人的平均薪资
df.groupby(['department_id', 'job_id'])[['salary']].mean()
df2 = df2.reset_index()
df2['salary'] = df2['salary'].round(1)
df2.sort_values('salary',ascending=False)
python 复制代码
import pandas as pd

# 模拟员工数据
data = {
    'department_id': [10,20,20,30,30,20,10],
    'job_id': [1001,1001,1002,1001,1002,1001,1002],
    'salary': [4500, 8000, 7000, 6500, 6000, 8500, 5500]
}
df = pd.DataFrame(data)

# 1. 按部门计算平均薪资
df2 = df.groupby('department_id')[['salary']].mean()
df2['salary'] = df2['salary'].round(2)
df2 = df2.reset_index()  # 注意:要赋值给df2,否则重置不生效!
df2 = df2.sort_values('salary', ascending=False)
print("各部门平均薪资(从高到低):")
print(df2)

# 2. 按部门+岗位计算平均薪资
df3 = df.groupby(['department_id', 'job_id'])[['salary']].mean().round(1)
df3 = df3.reset_index()
print("\n各部门-岗位平均薪资:")
print(df3)



各部门平均薪资(从高到低):
   department_id  salary
1             20  7833.33
2             30  6250.00
0             10  5000.00

各部门-岗位平均薪资:
   department_id  job_id  salary
0             10    1001   4500.0
1             10    1002   5500.0
2             20    1001   8250.0
3             20    1002   7000.0
4             30    1001   6500.0
5             30    1002   6000.0

最后总结分组聚合的核心步骤

  1. 数据清洗:保证分组字段无缺失、格式正确;
  2. 分组df.groupby(分组字段) → 把数据分堆;
  3. 选字段[聚合字段] → 确定要计算的列;
  4. 聚合.聚合函数() → 对每堆计算统计值;
  5. 格式化:round ()(保留小数)、reset_index ()(重置索引)、sort_values ()(排序)→ 让结果更易读。

案例分析

企鹅数据分析

python 复制代码
# 企鹅数据分析
# 1. 导入必要的库
import pandas as pd
# 2. 导入数据
df = pd.read_csv('data/penguins.csv')
df.head(5)
df.info()
# 3. 数据清洗
# 4. 数据特征的构造
# 5. 数据分析
python 复制代码
# 3. 数据清洗
# 缺失值检查
print(df.isna().sum())
df.dropna(inplace=True) # 当场去掉缺失值df就直接发送变化
# 4. 数据特征的构造
# 5. 数据分析
python 复制代码
df.isna().sum()
len(df)
# 4. 数据特征的构造
# 5. 数据分析
python 复制代码
# 4. 数据特征的构造
df['sex'] = df['sex'].astype('category')
df['bill_ratio'] = df['bill_length_mm'] / df['bill_depth_mm']
# 5. 数据分析
# 数据分箱 - 把体重分为三个等级
labels = ['低', '中', '高']
df['mass_level'] = pd.cut(df['body_mass_g'], bins=3, labels=labels)
print(df['mass_level'].value_counts())

# 按岛屿、 性别分组分析
df.groupby(['sex', 'island']).agg({
    'body_mass_g': ['mean', 'count'],
})

睡眠质量分析

python 复制代码
# 1. 导入库
import pandas as pd
import numpy as np

# 2. 导入数据
df = pd.read_csv('data/sleep.csv')
df.head()
df.info()
df.describe()
python 复制代码
# 3. 数据清洗 查看是否有缺失值
df.isna().sum()
df.drop(columns='sleep_disorder', inplace=True)

# 4. 数据特征的构造
df['gender'] = df['gender'].astype('category')
df['occupation'] = df['occupation'].astype('category')
df['bmi_category'] = df['bmi_category'].astype('category')
df[['high', 'low']] = df['blood_pressure'].str.split('/', expand=True)
df.head()

# 睡眠质量的分箱
labels = ['差', '中', '优']
df['quality_level'] =  pd.cut(df['sleep_quality'], bins=3, labels=labels)
age_labels=['青少年', '中年', '老年']
df['age_level'] = pd.cut(df['age'], bins=3, labels=age_labels)
df.head()
python 复制代码
# 5. 数据的统计与分析
print(df['bmi_category'].value_counts())
python 复制代码
# 根据不同的bmi 分组 睡眠质量
df.groupby('bmi_category').agg({
    'sleep_duration': 'mean',
    'sleep_quality': 'mean',
    'stress_level': 'mean',
})

总结不易~ 本章节对我有很大的收获, 希望对你也是!!!

相关推荐
_一路向北_8 小时前
爬虫框架:Feapder使用心得
爬虫·python
皇族崛起8 小时前
【3D标注】- Unreal Engine 5.7 与 Python 交互基础
python·3d·ue5
你想知道什么?9 小时前
Python基础篇(上) 学习笔记
笔记·python·学习
曼巴UE59 小时前
UE5 C++ 动态多播
java·开发语言
steins_甲乙9 小时前
C++并发编程(3)——资源竞争下的安全栈
开发语言·c++·安全
Swizard9 小时前
速度与激情:Android Python + CameraX 零拷贝实时推理指南
android·python·ai·移动开发
一直跑10 小时前
Liunx服务器centos7离线升级内核(Liunx服务器centos7.9离线/升级系统内核)
python
leocoder10 小时前
大模型基础概念入门 + 代码实战(实现一个多轮会话机器人)
前端·人工智能·python
Buxxxxxx10 小时前
DAY 37 深入理解SHAP图
python
ada7_10 小时前
LeetCode(python)108.将有序数组转换为二叉搜索树
数据结构·python·算法·leetcode