【Python 零基础入门】第七课 Pandas

  • 【Python 零基础入门】第七课 Pandas
  • Pandas 是什么?
  • 为什么 选择 Pandas
    • Pandas 的特征
    • Pandas 的应用场景
    • Pandas 底层
  • 安装 Pandas
  • Series 数组
    • 什么是 Series?
    • Series 创建
  • Series 数组操作
    • 数据检索
    • 数据修改
    • 过滤
    • Series 数组运算
    • 总结
  • DataFrame 数组
    • 什么是 DataFrame?
    • DataFrame 创建
  • 数据操作
    • 访问列数据
    • 访问行数据
    • loc vs iloc vs ix
  • DataFrame 操作
    • 筛选数据
    • 排序
    • 聚合
    • 增删
  • 数据加载
    • CSV 文件加载
    • Excel 文件加载
    • 数据探索
  • Pandas 缺失值填充
    • 识别缺失值
    • 使用“`dropna()“`舍弃缺失值
    • 使用“`fillna()“`填充缺失值
    • 去重
    • inplace 参数
  • 数据合并, 连接与管理
    • 合并
    • 分组与聚合
    • 时间序列分析
    • 数据可视化
  • 总结
  • 练习
    • 数据集介绍
    • 数据记载
    • 数据初步探索
    • 数据筛选与操作
    • 数据统计与聚合
    • 数据清洗
    • 数据可视化
  • 参考答案

【Python 零基础入门】第七课 Pandas

Pandas 是一个开源的 Python 数据分析库, 由 Wes McKinney 在 2008 年创建, 而且在接下来的几年中, 它迅速成为 Python 数据分析社区中最受欢迎和最有影响力的工具之一. Pandas 的名字来源于 Panel Data 和 Python Data Analysis.

Pandas 是什么” />

为什么 选择 Pandas

Pandas 的特征

对于我们开发者来说, Pandas 提供了一个强大的, 易于使用的数据结构和数据分析. Pandas 是数据清洗, 转换, 分析和可视化的首选.

列举一点 Pandas 的特点:

  • 灵活的数据结构: Pandas 轻松的处理各种不同类型的数据, 如结构化数值表, 时间序列, 统计数据集等
  • 功能强大的数据处理能力: 包括数据缺失, 插入, 删除, 聚合, 分析, 数据透视等操作
  • 易于与其他 Python 库集成: 例如 Matplotlib, Numpy 等

Pandas 的应用场景

Pandas 的主要应用场景:

  • 数据清洗: 如处理丢失的数据, 过滤数据等
  • 数据转换: 如创建新的数据结构, 聚合数据等
  • 数据分析: 如计算统计量, 对数据进行分组和汇总等
  • 数据可视化: 与其他库 (Matplotlib, Seaborn) 结合, 绘制可视化图表

Pandas 底层

底层实现:

  • Pandas 的底层是基于 Numpy 构建的, 这意味着 Pandas 的数据而机构, 如 “Series” 和 “DataFrame” 实际上都是在 Numpy 数组上进行操作的. 因为 Numpy 专门针对数值计算进行了优化, 所以 Pandas 在处理大量数据时性能很高
  • C 语言扩展: 虽然 Pandas 本身是用 Python 编写的, 但 Pandas 使用 Cython 来编写关键代码部分, 从而进一步提高性能

安装 Pandas

在 cmd 中输入:

pip install pandas

在 conda 中安装:

conda install pandas

查看是否安装成功:

import pandas as pd

Series 数组

Pandas 有两个核心的数据结构. “Series” 和 “DataFrame”. 我们先来讲 Series.

什么是 Series?

Series 是一个一维的标签化数组, Series 它可以容纳任何数据类型 (整型, 字符串, 浮点数, Python 对象等). Series 与普通的 Python 列表相似, 但是具有更多的功能和灵活性.

Series 创建

格式:

pd.Series(data, index=None, dtype=None, name=None, copy=None, fastpath=False)

参数:

  • data: 列表状数据
  • index: 索引, 默认为 None
  • drype: 返回的 Series 数组的类型, 默认为 None
  • name: Series 数组的名字, 默认为 None
  • copy: 复制输入的数据, 默认为 None

例子:

import pandas as pd# 创建 Series 数组list1 = [1, 2, 3]# 创建列表series1 = pd.Series(list1)# 通过 list 创建 Series 数组print(series1) # 调试输出import pandas as pd# 创建 Series 数组, 带 Indexstudent_name = ["张三", "李四", "我是小白呀"]# 创建学生名字列表, 用于索引学生idstudent_id = [1, 2, 3]# 创建学生 id 列表series2 = pd.Series(student_id, index=student_name)# 创建 Series 数组print(series2)# 调试输出# 通过字典创建 Series 数组dict1 = {'a':1,'b':2, 'c':3}# 创建字典series3 = pd.Series(dict1)# 通过字典创建 Series 数组print(series3)# 调试输出

输出结果:

011223dtype: int64张三 1李四 2我是小白呀3dtype: int64a1b2c3dtype: int64

Series 数组操作

数据检索

Series 数组中, 我们可以通过索引来实现数据检索.

例子:

import pandas as pd# 创建 Series 数组, 带 Indexstudent_name = ["张三", "李四", "我是小白呀"]# 创建学生名字列表, 用于索引学生idstudent_id = [1, 2, 3]# 创建学生 id 列表series1 = pd.Series(student_id, index=student_name)# 创建 Series 数组print(series1)# 调试输出# 数据检索zhangsan_id = series1["张三"]# 通过索引提取张三对应的 idlisi_id = series1["李四"]# 通过索引提取李四对应的 idiamarookie_id = series1["我是小白呀"]# 通过索引提取小白对应的 idprint("张三的 id:", zhangsan_id)print("李四的 id:", lisi_id)print("张三的 id:", iamarookie_id)# 多重检索ids = series1[["张三", "李四"]]# 通过索引提取张三和李四的 idprint("张三 & 李四的 id: \n{}".format(ids))# 调试输出

输出结果:

张三 1李四 2我是小白呀3dtype: int64张三的 id: 1李四的 id: 2张三的 id: 3张三 & 李四的 id: 张三1李四2dtype: int64

数据修改

Series 数组中, 可以用过索引来修改 Series 中的数据.

例子:

import pandas as pd# 创建 Series 数组, 带 Indexstudent_name = ["张三", "李四", "我是小白呀"]# 创建学生名字列表, 用于索引学生idstudent_id = [1, 2, 3]# 创建学生 id 列表series1 = pd.Series(student_id, index=student_name)# 创建 Series 数组print(series1)# 调试输出# 数据修改series1["张三"] = 123# 将 Series 数组中, 索引张三对应的 id 修改为 123print(series1)# 调试输出

输出结果:

张三 1李四 2我是小白呀3dtype: int64张三 123李四 2我是小白呀3dtype: int64

过滤

Series 数组可以用过布尔索引来实现数据过滤.

例子:

import pandas as pd# 创建关于学生成绩的 Series 数组student_name = ["张三", "李四", "我是小白呀"]# 创建学生名字列表, 用于索引学生成绩student_grade = [88, 90, 55]# 创建学生成绩列表series1 = pd.Series(student_grade, index=student_name)# 创建 Series 数组print(series1)# 调试输出# 数据修改result = series1[series1 < 60]print("成绩不及格的同学: \n{}".format(result))# 调试输出

输出结果:

张三 88李四 90我是小白呀55dtype: int64成绩不及格的同学: 我是小白呀55dtype: int64

Series 数组运算

import pandas as pd# 创建关于学生成绩的 Series 数组student_name = ["张三", "李四", "我是小白呀"]# 创建学生名字列表, 用于索引学生成绩student_grade = [88, 90, 55]# 创建学生成绩列表series1 = pd.Series(student_grade, index=student_name)# 创建 Series 数组print("加分前: \n{}".format(series1))# 调试输出# Series 数组运算series1 = series1 + 5# 鉴于小白同学不及格, 老师觉得给大家都加 5 分print("加分后: \n{}".format(series1))# 调试输出

输出结果:

加分前: 张三 88李四 90我是小白呀55dtype: int64加分后: 张三 93李四 95我是小白呀60dtype: int64

总结

Pandas 中的 Series 提供了一种灵活且强大的方式来处理数据. 无论是数据分析, 数据清洗还是数据操作, Series 都是一个非常有用的工具.

DataFrame 数组

什么是 DataFrame?

DataFrame 是一个二维的标签化数据结构, 类似于一个 Excel 表格. DataFrame 中的值都是相同长度的 Series, DataFrame 是 Pandas 最常用和强大的数据结构.

DataFrame 创建

通过使用pd.DataFrame函数我们可以创建 DataFrame 数组, DataFrame 可以由多种数据穿点, 如字典, 列表, 或外部文件.

格式:

pd.DataFrame(data=None, index=None, columns=None, dtype=None, copy=None)

参数:

  • data: 列表状数据
  • index: 索引, 默认为 None
  • columns: 列名, 默认为 None
  • detype: 返回的 Series 数组的类型, 默认为 None
  • copy: 复制输入的数据, 默认为 None

例子:

import pandas as pd# 创建 DataFrame 数组data = {"名字":["张三", "李四", "我是小白呀"], "年龄":[25, 32, 18]}# 创建字典df = pd.DataFrame(data)# 由字典创建 DataFrame 数组print(df)# 调试输出

输出结果:

名字年龄0 张三251 李四322我是小白呀18

数据操作

在 Pandas 中, 索引是一个非常强大的工具, 可以帮我我们更有效的访问, 查询和操作数据. 在了解数据结构后, 我们需要理解如何利用索引进行数组操作.

访问列数据

通过列名, 我们可以检索 DataFrame 中的数据.

数据:

名字年龄第一行 张三25第二行 李四32第三行我是小白呀18

例子:

import pandas as pd# 创建 DataFrame 数组data = {"名字":["张三", "李四", "我是小白呀"], "年龄":[25, 32, 18]}# 创建字典df = pd.DataFrame(data, index=["第一行", "第二行", "第三行"])# 由字典创建 DataFrame 数组print(df)# 调试输出# 检索名字列name = df["名字"]# 提取名字列print("提取名字列: \n{}".format(name))# 调试输出# 通过 iloc 实现切片name = df.iloc[:,0]# 提取名字列 (所有行, 第一列)print("提取名字列: \n{}".format(name))# 调试输出# 通过 loc 实现切片name = df.loc[:,"名字"]# 提取名字列print("提取名字列: \n{}".format(name))# 调试输出

输出结果:

名字年龄第一行 张三25第二行 李四32第三行我是小白呀18提取名字列: 第一行 张三第二行 李四第三行我是小白呀Name: 名字, dtype: object提取名字列: 第一行 张三第二行 李四第三行我是小白呀Name: 名字, dtype: object提取名字列: 第一行 张三第二行 李四第三行我是小白呀Name: 名字, dtype: object

访问行数据

例子:

import pandas as pd# 创建 DataFrame 数组data = {"名字":["张三", "李四", "我是小白呀"], "年龄":[25, 32, 18]}# 创建字典df = pd.DataFrame(data, index=["第一行", "第二行", "第三行"])# 由字典创建 DataFrame 数组print(df)# 调试输出# 检索第一行row0 = df.iloc[0]# 提取第一行print("提第一行: \n{}".format(row0))# 调试输出# 检索第一行row0 = df.loc["第一行"]# 提取第一行print("提第一行: \n{}".format(row0))# 调试输出

输出结果:

名字年龄第一行 张三25第二行 李四32第三行我是小白呀18提第一行: 名字张三年龄25Name: 第一行, dtype: object提第一行: 名字张三年龄25Name: 第一行, dtype: object

loc vs iloc vs ix

在 Pandas 中, loc, iloc, ix都是用于选择数据的方法.

三者区别:

  • loc[“行”,“列”]: 通过标签来选择数据
    • 选择行: df.loc[“行标签名”]
    • 选择列:df.loc[:,“列标签名”]
  • iloc[行索引, 列索引]: 通过索引来选择数据
    • 选择行: df.iloc[行索引]
    • 选择列: df.iloc[列索引]
  • ix: 既可以通过标签也可以通过索引, 约等于 loc 的功能 + iloc (了解即可)
    • 为了代码的可读性, 建议使用 loc 或 iloc, ix 现已被废弃, 不建议使用

DataFrame 操作

筛选数据

例子:

import pandas as pd# 创建 DataFrame 数组data = {"名字":["张三", "李四", "我是小白呀"], "年龄":[25, 32, 18]}# 创建字典df = pd.DataFrame(data)# 由字典创建 DataFrame 数组print(df)# 调试输出# 检索名字列name = df["名字"]# 提取名字列print("提取名字列: \n{}".format(name))# 调试输出

输出结果:

名字年龄0 张三251 李四322我是小白呀18提取名字列: 0 张三1 李四2我是小白呀Name: 名字, dtype: object

排序

格式:

pd.DataFrame.sort_values(by, *, axis=0, ascending=True, inplace=False, kind='quicksort', na_position='last', ignore_index=False, key=None)

参数:

  • axis: 轴, 默认为纵向排序
  • ascending: 从低到高
  • inplace: 替换原本 DataFrame, 默认为 False

例子:

import pandas as pd# 创建 DataFrame 数组data = {"名字":["张三", "李四", "我是小白呀"], "年龄":[25, 32, 18]}# 创建字典df = pd.DataFrame(data)# 由字典创建 DataFrame 数组print(df)# 调试输出# DataFrame 排序df = df.sort_values(by="年龄")# 通过布尔条件筛选特定数据df.reset_index(inplace=True)# 重新索引print("排序: \n{}".format(df))# 调试输出

注: 通过df.reset_index(inplace=True), DataFrame 数组会进行重新索引.

聚合

我们可以对 DataFrame 数字进行各种聚合操作.

例子:

import pandas as pd# 创建 DataFrame 数组data = {"名字":["张三", "李四", "我是小白呀"], "年龄":[25, 32, 18]}# 创建字典df = pd.DataFrame(data)# 由字典创建 DataFrame 数组print(df)# 调试输出# DataFrame 聚合mean = df["年龄"].mean()# 通过布尔条件筛选特定数据print("平均年龄:", mean)# 调试输出

输出结果:

名字年龄0 张三251 李四322我是小白呀18平均年龄: 25.0

增删

import pandas as pd# 创建 DataFrame 数组data = {"名字":["张三", "李四", "我是小白呀"], "年龄":[25, 32, 18]}# 创建字典df = pd.DataFrame(data)# 由字典创建 DataFrame 数组print(df)# 调试输出# 添加列data["成绩"] = [78, 82, 60]# 添加一个新的列, 成绩print(df)# 调试输出# 删除列del data["年龄"]# 删除年龄列print(df)

输出结果:

名字年龄0 张三251 李四322我是小白呀18名字年龄0 张三251 李四322我是小白呀18名字年龄0 张三251 李四322我是小白呀18

数据加载

我们经常会遇到需要从 csv 文件中加塞数据的情况. Pandas 中提供了read_csv方法, 使得我们从 csv 文件中加载数据变得非常简单.

CSV 文件加载

格式:

pandas.read_csv(filepath_or_buffer, *, sep=_NoDefault.no_default, delimiter=None, header='infer', names=_NoDefault.no_default, index_col=None, usecols=None, dtype=None, engine=None, converters=None, true_values=None, false_values=None, skipinitialspace=False, skiprows=None, skipfooter=0, nrows=None, na_values=None, keep_default_na=True, na_filter=True, verbose=False, skip_blank_lines=True, parse_dates=None, infer_datetime_format=_NoDefault.no_default, keep_date_col=False, date_parser=_NoDefault.no_default, date_format=None, dayfirst=False, cache_dates=True, iterator=False, chunksize=None, compression='infer', thousands=None, decimal='.', lineterminator=None, quotechar='"', quoting=0, doublequote=True, escapechar=None, comment=None, encoding=None, encoding_errors='strict', dialect=None, on_bad_lines='error', delim_whitespace=False, low_memory=True, memory_map=False, float_precision=None, storage_options=None, dtype_backend=_NoDefault.no_default)

参数:

  • filepath_or_buffer: 文件路径
  • header: 表头
  • names: 列名

例子:

import pandas as pd# 读取 txt/csvdata = pd.read_csv("test.txt", header=None, names=["链接"])print(data)# 调试输出

输出结果:

链接0http://melanz.phorum.pl/viewtopic.php?f=7&t=640411http://www.reo14.moe.go.th/phpBB3/viewtopic.ph...2https://www.xroxy.com/xorum/viewtopic.php?p=30...3http://armasow.forumbb.ru/viewtopic.php?id=840...4http://telecom.liveforums.ru/viewtopic.php?id=...5http://www.crpsc.org.br/forum/viewtopic.php?f=...6http://community.getvideostream.com/topic/4803...7http://www.shop.minecraftcommand.science/forum...8https://www.moddingway.com/forums/thread-31914...9https://webhitlist.com/forum/topics/main-featu...

Excel 文件加载

例子:

df = pd.read_excel('path_to_file.xlsx')

数据探索

在 DataFrame 中, 我们可以用过一些函数来查看 DataFrame 数据的基本结构和内容.

常用函数:

  • df.info(): 返回数据基本信息, 包括数据类型, 非空等
  • df.head(): 显示前 5 行
  • df.tail(): 显示最后 5 行
  • df.describe(): 显示基本统计信息, 包括: 如平均值, 标准差, 最小值, 25th, 50th (中位数) 和 75th 百分位数, 最大值等

例子:

import pandas as pd# 读取数据data = pd.read_csv("students.txt", header=None)print(data.info())# 显示总览, 包括每列的数据类型和非空值的数量print(data.head())# 显示前 5 行print(data.tail())# 显示后 5 行print(data.describe())# 显示基本统计信息

调试输出:

RangeIndex: 131 entries, 0 to 130Data columns (total 2 columns):0131 non-null object1131 non-null objectdtypes: object(2)memory usage: 2.1+ KBNone0 10c1235666 Fink-NottleAugustus James1c3456765 O'MahoneyGeoffrey2 c8732719 De Leo Victoria Margaret3 c9676814 Thompson Sabrina4 c4418710 Heck Kevin01126 c6060052 LongMarilyn127c2390980 Martz Perry Tony William128 c5456142 WilsonChristine Mabel129c1036678 BunchRichard Frank130c8306065 Hartley Marcel Jonathan Philip01count 131131unique131127top c3827371 Bush Thomasfreq12

Pandas 缺失值填充

大多情况下, 数据可能不总是完整的, 所以我们要处理数据丢失. Pandas 提供了多种处理缺失数据的方法.

识别缺失值

在 Pandas 中, 缺失值通常表示为 “NaN” (Not a Number). 我们可以使用isnull()函数或者isna()函数来列出数据中的缺失值.

以下数据就缺失 Fare 列中的几个值:

 PassengerIdSurvivedPclass...FareCabinEmbarked01 0 3...7.2500NaN S12 1 1... 71.2833C85 C23 1 3...7.9250NaN S34 1 1... 53.1000 C123 S

例子:

import pandas as pd# 读取数据data = pd.read_csv("train.csv")print(data)# 调试输出每列的缺失值print(data.isnull().sum())

输出结果:

 PassengerIdSurvivedPclass...FareCabinEmbarked01 0 3...7.2500NaN S12 1 1... 71.2833C85 C23 1 3...7.9250NaN S34 1 1... 53.1000 C123 S45 0 3...8.0500NaN S56 0 3...8.4583NaN Q67 0 1... 51.8625E46 S78 0 3... 21.0750NaN S89 1 3... 11.1333NaN S9 10 1 2... 30.0708NaN C1011 1 3... 16.7000 G6 S1112 1 1... 26.5500 C103 S1213 0 3...8.0500NaN S1314 0 3... 31.2750NaN S1415 0 3...7.8542NaN S1516 1 2... 16.0000NaN S1617 0 3... 29.1250NaN Q1718 1 2... 13.0000NaN S1819 0 3... 18.0000NaN S1920 1 3...7.2250NaN C2021 0 2... 26.0000NaN S2122 1 2... 13.0000D56 S2223 1 3...8.0292NaN Q2324 1 1... 35.5000 A6 S2425 0 3... 21.0750NaN S2526 1 3... 31.3875NaN S2627 0 3...7.2250NaN C2728 0 1...263.0000C23 C25 C27 S2829 1 3...7.8792NaN Q2930 0 3...7.8958NaN S.. ... ... ...... ...... ...861862 0 2... 11.5000NaN S862863 1 1... 25.9292D17 S863864 0 3... 69.5500NaN S864865 0 2... 13.0000NaN S865866 1 2... 13.0000NaN S866867 1 2... 13.8583NaN C867868 0 1... 50.4958A24 S868869 0 3...9.5000NaN S869870 1 3... 11.1333NaN S870871 0 3...7.8958NaN S871872 1 1... 52.5542D35 S872873 0 1...5.0000B51 B53 B55 S873874 0 3...9.0000NaN S874875 1 2... 24.0000NaN C875876 1 3...7.2250NaN C876877 0 3...9.8458NaN S877878 0 3...7.8958NaN S878879 0 3...7.8958NaN S879880 1 1... 83.1583C50 C880881 1 2... 26.0000NaN S881882 0 3...7.8958NaN S882883 0 3... 10.5167NaN S883884 0 2... 10.5000NaN S884885 0 3...7.0500NaN S885886 0 3... 29.1250NaN Q886887 0 2... 13.0000NaN S887888 1 1... 30.0000B42 S888889 0 3... 23.4500NaN S889890 1 1... 30.0000 C148 C890891 0 3...7.7500NaN Q[891 rows x 12 columns]PassengerId0Survived 0Pclass 0Name 0Sex0Age177SibSp0Parch0Ticket 0Fare 0Cabin687Embarked 2dtype: int64

使用dropna()舍弃缺失值

df.dropna()可以帮助我们删除数据中所有缺失的行.

例子:

import pandas as pdimport numpy as np# 创建一个模拟数据集data = {'Product': ['Apple', 'Banana', 'Cherry', 'Date', 'Fig', 'Grape', 'Mango', 'Watermelon'],'Price': [1, 0.5, np.nan, 0.75, np.nan, 2.5, 1.2, np.nan],'Date_sold': [np.nan, '2023-01-15', '2023-01-16', '2023-01-17', '2023-01-18', '2023-01-19', np.nan, '2023-01-21']}df = pd.DataFrame(data)print("原始数据:")print(df)# 删除任何含有 NaN 的行df_dropped = df.dropna()print("\n删除含有 NaN 后的数据:")print(df_dropped)

输出结果:

原始数据:ProductPrice Date_sold0 Apple 1.00 NaN1Banana 0.502023-01-152CherryNaN2023-01-163Date 0.752023-01-174 FigNaN2023-01-185 Grape 2.502023-01-196 Mango 1.20 NaN7WatermelonNaN2023-01-21删除含有 NaN 后的数据:ProductPrice Date_sold1Banana 0.502023-01-153Date 0.752023-01-175 Grape 2.502023-01-19

使用fillna()填充缺失值

df.fillna()帮助我们使用指定的值填充缺失数据.

例子:

import pandas as pdimport numpy as np# 创建一个模拟数据集data = {'Product': ['Apple', 'Banana', 'Cherry', 'Date', 'Fig', 'Grape', 'Mango', 'Watermelon'],'Price': [1, 0.5, np.nan, 0.75, np.nan, 2.5, 1.2, np.nan],'Date_sold': [np.nan, '2023-01-15', '2023-01-16', '2023-01-17', '2023-01-18', '2023-01-19', np.nan, '2023-01-21']}df = pd.DataFrame(data)print("原始数据:")print(df)# 使用固定值填充df1 = df.copy()df1['Price'].fillna("1", inplace=True)print("\n使用固定值填充后的数据:")print(df1)# 使用前一个值填充df2 = df.copy()df2['Price'].fillna(method='ffill', inplace=True)print("\n使用前一个值填充后的数据:")print(df2)# 使用平均值填充df3 = df.copy()df3['Price'].fillna(df3['Price'].mean(), inplace=True)print("\n使用平均值填充后的数据:")print(df3)

输出结果:

原始数据:ProductPrice Date_sold0 Apple 1.00 NaN1Banana 0.502023-01-152CherryNaN2023-01-163Date 0.752023-01-174 FigNaN2023-01-185 Grape 2.502023-01-196 Mango 1.20 NaN7WatermelonNaN2023-01-21使用固定值填充后的数据:Product Price Date_sold0 Apple 1 NaN1Banana 0.52023-01-152Cherry 12023-01-163Date0.752023-01-174 Fig 12023-01-185 Grape 2.52023-01-196 Mango 1.2 NaN7Watermelon 12023-01-21使用前一个值填充后的数据:ProductPrice Date_sold0 Apple 1.00 NaN1Banana 0.502023-01-152Cherry 0.502023-01-163Date 0.752023-01-174 Fig 0.752023-01-185 Grape 2.502023-01-196 Mango 1.20 NaN7Watermelon 1.202023-01-21使用平均值填充后的数据:ProductPrice Date_sold0 Apple 1.00 NaN1Banana 0.502023-01-152Cherry 1.192023-01-163Date 0.752023-01-174 Fig 1.192023-01-185 Grape 2.502023-01-196 Mango 1.20 NaN7Watermelon 1.192023-01-21

去重

去重:

df.drop.duplicates()

数据转换:

df['column_name'] = df['column_name'].astype('new_type')# 转换数据类型df['new_column'] = df['column1'] + df['column2']

inplace 参数

Pandas 中 inplace 参数在很多函数中都会有, 它的作用是: 是否在原对象基础上进行修改.

inplace 中 True 和 False 的意思:

  • inplace = True: 不创建新的对象, 直接对原始对象进行修改
  • inplace = False: 对数据进行修改, 创建并返回新的对象承载其修改结果

例子:

# 以下两行代码意思相同df.dropna(inplace=True)# 直接对 df 对象进行修改df_dropped = df.dropna(inplace=True)# 对 df 进行修改并返回对象

inplace 参数在函数中默认是 False,即创建新的对象进行修改, 原对象不变, 和深复制和浅复制有些类似.

数据合并, 连接与管理

合并

contact()函数可以帮助我们连接两个或者多个数据.

格式:

df.concat(objs, axis=0, join='outer', join_axes=None, ignore_index=False, keys=None, levels=None, names=None, verify_integrity=False, sort=None, copy=True)

参数:

  • objs: 需要拼接的数字
  • join: 拼接模式
  • join_axes: 拼接轴

例子:

import pandas as pd# 初始化 DataFrame 数组df1 = pd.DataFrame({'A': ['A0', 'A1', 'A2'], 'B': ['B0', 'B1', 'B2']})df2 = pd.DataFrame({'A': ['A3', 'A4', 'A5'], 'B': ['B3', 'B4', 'B5']})# 调试输出print(df1)print(df2)# 进行 concat 连接result = pd.concat([df1, df2])print(result)

调试输出:

A B0A0B01A1B12A2B2A B0A3B31A4B42A5B5A B0A0B01A1B12A2B20A3B31A4B42A5B5

“`merge()“函数也可以帮助我们进行合并操作, 类似于 SQL 的 JOIN.

例子:

import pandas as pd# 初始化 DataFrame 数组left = pd.DataFrame({'key': ['K0', 'K1', 'K2'], 'A': ['A0', 'A1', 'A2'], 'B': ['B0', 'B1', 'B2']})right = pd.DataFrame({'key': ['K0', 'K1', 'K2'],'C': ['C0', 'C1', 'C2'],'D': ['D0', 'D1', 'D2']})# 调试输出print(left)print(right)# 使用 merge 拼接result = pd.merge(left, right, on='key')print(result)

输出结果:

key A B0K0A0B01K1A1B12K2A2B2key C D0K0C0D01K1C1D12K2C2D2key A B C D0K0A0B0C0D01K1A1B1C1D12K2A2B2C2D2

分组与聚合

使用groupby()可以将数组框按列值分组, 然后对每个组应用聚合函数.

常见的聚合函数:

  • sum(): 求和
  • mean(): 平均数
  • median(): 求中位数
  • min(): 求最小值
  • max(): 求最大值

例 1:

import pandas as pd# 初始化 DataFrame 数组df = pd.DataFrame({'A': ['foo', 'bar', 'foo', 'bar'], 'B': [1, 2, 3, 4], 'C': [2.0, 3.0, 4.0, 5.0]})print(df)# 聚合求和grouped = df.groupby('A').sum()print(grouped)

调试输出:

 ABC0foo12.01bar23.02foo34.03bar45.0 BCAbar68.0foo46.0

例 2, 关于全球员工薪水的数据集:

import pandas as pd# 数据集data = {'Country': ['USA', 'India', 'UK', 'USA', 'India', 'UK', 'USA', 'India'],'Employee': ['Sam', 'Amit', 'John', 'Alice', 'Alok', 'Bob', 'Charlie', 'Deepak'],'Salary': [70000, 45000, 60000, 80000, 50000, 55000, 85000, 65000]}# 初始化 DataFramedf = pd.DataFrame(data)print(df)# 使用 goupby() 根据国家计算平均薪水salary_by_country = df.groupby("Country")["Salary"].mean()print("平均薪水:", salary_by_country)# 使用 groupby() 计算每个国家的员工数employee_by_country = df.groupby("Country")["Employee"].count()print("员工数量: \n{}",format(employee_by_country))# 多重聚合result = df.groupby("Country")['Salary'].agg(['mean', 'median', 'sum', 'max', 'min'])print(result)

输出结果:

Country EmployeeSalary0 USASam 700001 India Amit 450002UK John 600003 USAAlice 800004 India Alok 500005UKBob 550006 USACharlie 850007 India Deepak 65000平均薪水: CountryIndia53333.333333UK 57500.000000USA78333.333333Name: Salary, dtype: float64员工数量: {} CountryIndia3UK 2USA3Name: Employee, dtype: int64 meanmedian summaxminCountryIndia53333.333333 500001600006500045000UK 57500.000000 575001150006000055000USA78333.333333 800002350008500070000

时间序列分析

Pandas 提供了 “datatime” 和 “timedelta” 类型, 用于处理时间数据.

例子:

import pandas as pd# 时间序列分析data = pd.to_datetime(['2023-01-01', '2023-02-01'])print(data)# 调试输出

输出结果:

DatetimeIndex(['2023-01-01', '2023-02-01'], dtype='datetime64[ns]', freq=None)

数据可视化

我们可以通过 Pandas 进行基本的数据可视化.

Pandas 除了能进行数据处理和分析的功能外, 还提供了简单直观的绘制方法:

  • ““plot()“`: 绘制线图, 通常用于时间序列数据
  • hist(): 绘制直方图, 有助于观察数据分布
  • boxpolt(): 绘制箱线图, 可用于观察数据的中位数, 分位数等统计指标

使用plot绘制线图:

import pandas as pdimport numpy as npimport matplotlib.pyplot as plt# 生成示例数据date_rng = pd.date_range(start='2020-01-01', end='2020-12-31', freq='D')df = pd.DataFrame(date_rng, columns=['date'])df['data'] = np.random.randint(0, 100, size=(len(date_rng)))df.set_index('date', inplace=True)df.plot(figsize=(10, 6))plt.title('Time Series Data Visualization')plt.ylabel('Random Data')plt.show()

输出结果:

使用hist()绘制直方图:

import pandas as pdimport numpy as npimport matplotlib.pyplot as plt# 生成示例数据date_rng = pd.date_range(start='2020-01-01', end='2020-12-31', freq='D')df = pd.DataFrame(date_rng, columns=['date'])df['data'] = np.random.randint(0, 100, size=(len(date_rng)))# 绘制直方图df['data'].hist(bins=30, figsize=(10, 6))plt.title('Histogram Data Visualization')plt.xlabel('Random Data')plt.ylabel('Frequency')plt.show()

输出结果:

使用boxplot()绘制箱线图:

import pandas as pdimport numpy as npimport matplotlib.pyplot as plt# 生成示例数据date_rng = pd.date_range(start='2020-01-01', end='2020-12-31', freq='D')df = pd.DataFrame(date_rng, columns=['date'])df['data'] = np.random.randint(0, 100, size=(len(date_rng)))# 绘制箱线图df.boxplot(column='data', figsize=(6, 10))plt.title('Boxplot Data Visualization')plt.ylabel('Random Data')plt.show()

输出结果:

总结

Pandas 在数据分析中的重要性. Pandas 是 Python 数据分析中的一个不可或缺的库. 通过 Pandas, 数据科学家和数据分析师能够轻松的读取, 处理, 分析和可视化数据.

首先,我们介绍了 Pandas 的核心数据结构——Series 和 DataFrame,它们分别为一维和二维数据提供了丰富的操作和功能。接着,我们详细讨论了如何对数据进行索引、选择和修改,使数据处理变得简单高效。

在数据清洗部分,我们学习了各种数据清洗技巧,如处理缺失值、重复数据和字符串操作。这些都是数据预处理过程中的关键步骤,对于后续的分析和模型建立至关重要。

之后,我们深入了解了数据的聚合、转换和过滤。通过对数据的分组和汇总,我们可以获得有关数据的有趣洞察和统计信息。

最后,我们探索了 Pandas 的高级特性,如数据的合并、重塑、透视以及如何处理大数据和性能优化。这些技巧可以帮助我们更好地组织和优化代码,使其更具可读性和效率。

总的来说,Pandas 是一个功能强大、灵活且高效的工具,无论你是数据初学者还是经验丰富的分析师,都应该深入学习和掌握它。希望本篇博客能为你的数据分析之旅提供有价值的参考和指导。继续探索、学习和实践,让数据的魅力助你走得更远!

练习

数据集介绍

泰坦尼克号数据集。这个数据集包含了泰坦尼克号上乘客的信息和他们是否在沉船事故中生还。

数据描述:

  • PassengerId:乘客编号
  • Survived:是否生还(0 = No, 1 = Yes)
  • Pclass:票的类别(1 = 1st, 2 = 2nd, 3 = 3rd)
  • Name:乘客姓名
  • Sex:性别
  • Age:年龄
  • SibSp:在船上的兄弟姐妹和配偶的数量
  • Parch:在船上的父母和子女的数量
  • Ticket:票号
  • Fare:票价
  • Cabin:船舱号
  • Embarked:登船港口(C = Cherbourg, Q = Queenstown, S = Southampton)

数据记载

下载泰坦尼克号数据集:点此下载
使用 Pandas 读取下载的 CSV 文件。

数据初步探索

数据初步探索:

  • 描述数据集的大小、列的数据类型。
  • 查看数据集中是否有缺失值,并决定如何处理它们。

数据筛选与操作

数据筛选与操作:

  • 选择 Pclass, Sex, 和 Survived 列进行进一步分析。
  • 找出所有在1等舱的女性乘客。
    创建一个新列 IsChild,标记年龄小于18岁的乘客。

数据统计与聚合

数据统计与聚合:

  • 计算女性乘客的平均生还率。
  • 对 Pclass 使用 groupby(),并计算每个类别的平均生还率。
  • 创建一个数据透视表,显示不同舱位和性别的生还率。

数据清洗

数据清洗:

  • 处理 Age 列的缺失值,可以考虑填充平均年龄或使用其他方法。
  • 根据姓名查找可能的重复乘客。
  • 将 Sex 列转换为数值型,如:0为male,1为female。

数据可视化

数据可视化:

  • 使用 Pandas 绘制不同 Pclass 的生还率条形图。
  • 绘制 Age 列的直方图,观察乘客年龄分布。
  • 对 Fare 列绘制箱线图,观察票价的分布。

参考答案

import pandas as pdfrom matplotlib import pyplot as plt# 读取数据data = pd.read_csv("train.csv")print(data)# 显示基本信息print(data.info())print(data.describe())print(data.isnull().sum())# 调试输出缺失值# 填充缺失data["Age"].fillna(data["Age"].mean(), inplace=True)# 填充平均值data['Cabin'].fillna('Unknown', inplace=True)print(data.isnull().sum())# 调试输出缺失值# 数据筛选与操作selected_data = data[['Pclass', 'Sex', 'Survived']]first_class_females = data[(data['Pclass'] == 1) & (data['Sex'] == 'female')]# 标记18岁以下的乘客data['IsChild'] = data['Age'].apply(lambda x: 1 if x < 18 else 0)# 数据统计与聚合female_survival_rate = data[data['Sex'] == 'female']['Survived'].mean()print(f"Female Survival Rate: {female_survival_rate}")class_survival_rates = data.groupby('Pclass')['Survived'].mean()print(class_survival_rates)pivot_table = data.pivot_table('Survived', index='Sex', columns='Pclass')print(pivot_table)# 数据清洗data['Sex'] = data['Sex'].map({'male': 0, 'female': 1})# 将 Sex 列转为数值型# 数据可视化class_survival_rates.plot(kind='bar', title='Survival Rates by Pclass')plt.ylabel('Survival Rate')plt.show()data['Age'].hist(bins=30, edgecolor='black')plt.title('Age Distribution')plt.xlabel('Age')plt.ylabel('Number of Passengers')plt.show()data['Fare'].plot(kind='box')plt.title('Fare Distribution')plt.ylabel('Fare')plt.show()

输出结果:

 PassengerIdSurvivedPclass...FareCabinEmbarked01 0 3...7.2500NaN S12 1 1... 71.2833C85 C23 1 3...7.9250NaN S34 1 1... 53.1000 C123 S45 0 3...8.0500NaN S56 0 3...8.4583NaN Q67 0 1... 51.8625E46 S78 0 3... 21.0750NaN S89 1 3... 11.1333NaN S9 10 1 2... 30.0708NaN C1011 1 3... 16.7000 G6 S1112 1 1... 26.5500 C103 S1213 0 3...8.0500NaN S1314 0 3... 31.2750NaN S1415 0 3...7.8542NaN S1516 1 2... 16.0000NaN S1617 0 3... 29.1250NaN Q1718 1 2... 13.0000NaN S1819 0 3... 18.0000NaN S1920 1 3...7.2250NaN C2021 0 2... 26.0000NaN S2122 1 2... 13.0000D56 S2223 1 3...8.0292NaN Q2324 1 1... 35.5000 A6 S2425 0 3... 21.0750NaN S2526 1 3... 31.3875NaN S2627 0 3...7.2250NaN C2728 0 1...263.0000C23 C25 C27 S2829 1 3...7.8792NaN Q2930 0 3...7.8958NaN S.. ... ... ...... ...... ...861862 0 2... 11.5000NaN S862863 1 1... 25.9292D17 S863864 0 3... 69.5500NaN S864865 0 2... 13.0000NaN S865866 1 2... 13.0000NaN S866867 1 2... 13.8583NaN C867868 0 1... 50.4958A24 S868869 0 3...9.5000NaN S869870 1 3... 11.1333NaN S870871 0 3...7.8958NaN S871872 1 1... 52.5542D35 S872873 0 1...5.0000B51 B53 B55 S873874 0 3...9.0000NaN S874875 1 2... 24.0000NaN C875876 1 3...7.2250NaN C876877 0 3...9.8458NaN S877878 0 3...7.8958NaN S878879 0 3...7.8958NaN S879880 1 1... 83.1583C50 C880881 1 2... 26.0000NaN S881882 0 3...7.8958NaN S882883 0 3... 10.5167NaN S883884 0 2... 10.5000NaN S884885 0 3...7.0500NaN S885886 0 3... 29.1250NaN Q886887 0 2... 13.0000NaN S887888 1 1... 30.0000B42 S888889 0 3... 23.4500NaN S889890 1 1... 30.0000 C148 C890891 0 3...7.7500NaN Q[891 rows x 12 columns]RangeIndex: 891 entries, 0 to 890Data columns (total 12 columns):PassengerId891 non-null int64Survived 891 non-null int64Pclass 891 non-null int64Name 891 non-null objectSex891 non-null objectAge714 non-null float64SibSp891 non-null int64Parch891 non-null int64Ticket 891 non-null objectFare 891 non-null float64Cabin204 non-null objectEmbarked 889 non-null objectdtypes: float64(2), int64(5), object(5)memory usage: 83.6+ KBNone PassengerIdSurvivedPclass... SibSp ParchFarecount 891.000000891.000000891.000000...891.000000891.000000891.000000mean446.0000000.3838382.308642...0.5230080.381594 32.204208std 257.3538420.4865920.836071...1.1027430.806057 49.693429min 1.0000000.0000001.000000...0.0000000.0000000.00000025% 223.5000000.0000002.000000...0.0000000.0000007.91040050% 446.0000000.0000003.000000...0.0000000.000000 14.45420075% 668.5000001.0000003.000000...1.0000000.000000 31.000000max 891.0000001.0000003.000000...8.0000006.000000512.329200[8 rows x 7 columns]PassengerId0Survived 0Pclass 0Name 0Sex0Age177SibSp0Parch0Ticket 0Fare 0Cabin687Embarked 2dtype: int64PassengerId0Survived 0Pclass 0Name 0Sex0Age0SibSp0Parch0Ticket 0Fare 0Cabin0Embarked 2dtype: int64Female Survival Rate: 0.7420382165605095Pclass10.62963020.47282630.242363Name: Survived, dtype: float64Pclass 1 2 3Sex female0.9680850.9210530.500000male0.3688520.1574070.135447