当前位置: 首页 > news >正文

【数据分析】03 - pandas

【数据分析】03 - pandas

文章目录

  • 【数据分析】03 - pandas
    • 一:Pandas入门
      • 1:Pandas概述
      • 2:Pands数据结构
    • 二:输入格式详解
      • 1:CSV
        • 1.1:基本使用
        • 1.2:数据处理
      • 2:Excel
        • 2.1:读取文件
        • 2.2:写入文件
        • 2.3:加载文件
        • 2.4:多个表单的写入
      • 3:JSON
        • 3.1:读取Json文件
        • 3.2:DF读取为JSON
    • 三:Pandas操作
      • 1:基本方法
        • 1.1:Series的基本方法
        • 1.2:DataFrame的基本方法
      • 2:描述性统计
        • 1.1:sum()
        • 1.2:mean()
        • 1.3:其他统计性函数
        • 1.4:汇总函数describe
      • 3:函数的应用
        • 3.1:表函数应用程序
        • 3.2:行或列函数应用程序
        • 3.3:元素级函数应用程序
      • 4:重建索引
        • 4.1:reindex()
        • 4.2:reindex_like()
        • 4.3:重命名
      • 5:迭代和排序
        • 5.1:迭代
        • 5.2:排序
      • 6:series的文本处理
      • 7:自定义选项的设置
      • 8:索引和数据查询
        • 8.1:loc
        • 8.2:iloc
    • 四:高级操作
      • 1:缺失值处理
        • 1.1:对于缺失值的表示
        • 1.2:对于缺失值的检测
        • 1.3:对于缺失值的删除
        • 1.4:对于缺失值的填充
        • 1.5:其他常用操作
      • 2:统计、分组和连接
        • 2.1:统计计算
        • 2.2:分组操作
        • 2.3:数据连接
        • 2.4:高级技巧
      • 3:日期相关操作
        • 3.1:日期的创建和转换
        • 3.2:日期时间属性提取
        • 3.3:日期时间运算
        • 3.4:时间序列操作
        • 3.5:日期索引操作
        • 3.6:其他常用操作
        • 3.7:完整实际实例演示
      • 4:数据分类
      • 5:可视化和SQL操作

一:Pandas入门

1:Pandas概述

Pandas 一个强大的分析结构化数据的工具集,基础是 numpy

Pandas 官网 https://pandas.pydata.org/

Pandas 源代码:https://github.com/pandas-dev/pandas

  • Pandas 可以从各种文件格式比如 CSV、JSON、SQL、Microsoft Excel 导入数据。
  • Pandas 可以对各种数据进行运算操作,比如归并、再成形、选择,还有数据清洗和数据加工特征。
  • Pandas 广泛应用在学术、金融、统计学等各个数据分析领域。

Pandas 是数据分析的利器,它不仅提供了高效、灵活的数据结构,还能帮助你以极低的成本完成复杂的数据操作和分析任务。

Pandas 提供了丰富的功能,包括:

  • 数据清洗:处理缺失数据、重复数据等。
  • 数据转换:改变数据的形状、结构或格式。
  • 数据分析:进行统计分析、聚合、分组等。
  • 数据可视化:通过整合 Matplotlib 和 Seaborn 等库,可以进行数据可视化。
# 安装pandas
pip install pandas
# 测试pandas的安装
import pandas as pddef pandas_test01():print(pd.__version__)if __name__ == '__main__':pandas_test01()

pandas的特点如下

高效的数据结构:

  • Series:一维数据结构,类似于列表(List),但拥有更强的功能,支持索引。
  • DataFrame:二维数据结构,类似于表格或数据库中的数据表,行和列都具有标签(索引)。

数据清洗与预处理:

  • Pandas 提供了丰富的函数来处理缺失值、重复数据、数据类型转换、字符串操作等,帮助用户轻松清理和转换数据。

数据操作与分析:

  • 支持高效的数据选择、筛选、切片,按条件提取数据、合并、连接多个数据集、数据分组、汇总统计等操作。
  • 可以进行复杂的数据变换,如数据透视表、交叉表、时间序列分析等。

数据读取与导出:

  • 支持从各种格式的数据源读取数据,如 CSV、Excel、JSON、SQL 数据库等。
  • 也可以将处理后的数据导出为不同格式,如 CSV、Excel 等。

数据可视化:

  • 通过与 Matplotlib 和其他可视化工具的集成,Pandas 可以快速生成折线图、柱状图、散点图等常见图表。

时间序列分析:

  • 支持强大的时间序列处理功能,包括日期的解析、重采样、时区转换等。

性能与优化:

  • Pandas 优化了大规模数据处理,提供高效的向量化操作,避免了使用 Python 循环处理数据的低效。
  • 还支持一些内存优化技术,比如使用 category 类型处理重复的数据。

2:Pands数据结构

Series + DataFrame

在这里插入图片描述
在这里插入图片描述

DataFrame 可视为由多个 Series 组成的数据结构:

  • index是自动生成的,表示记录1 ~ 记录n
  • 每一列表示一个Series, 列的名称就是key

在这里插入图片描述

在这里插入图片描述

DataFrame = key + value + index

在这里插入图片描述

import pandas as pddef pandas_test01():print(pd.__version__)def pandas_test02():# 创建两个Series对象series_apples = pd.Series([1, 3, 7, 4])series_bananas = pd.Series([2, 6, 3, 5])# 将两个Series对象相加,得到DataFrame,并指定列名df = pd.DataFrame({'Apples': series_apples, 'Bananas': series_bananas})# 显示DataFrameprint(df)if __name__ == '__main__':pandas_test02()

在这里插入图片描述

二:输入格式详解

1:CSV

CSV 是一种通用的、相对简单的文件格式,被用户、商业和科学广泛应用。

1.1:基本使用

pandas和CSV之间就是两个方法:

  • 从CSV中读取数据,并加载成为DataFrame -> pd.read_csv()
  • 将DataFrame中的内容写入到CSV -> DataFrame.to_csv()

read_csv 常用参数:

参数说明默认值
filepath_or_bufferCSV 文件的路径或文件对象(支持 URL、文件路径、文件对象等)必需参数
sep定义字段分隔符,默认是逗号(,),可以改为其他字符,如制表符(\t','
header指定行号作为列标题,默认为 0(表示第一行),或者设置为 None 没有标题0
names自定义列名,传入列名列表None
index_col用作行索引的列的列号或列名None
usecols读取指定的列,可以是列的名称或列的索引None
dtype强制将列转换为指定的数据类型None
skiprows跳过文件开头的指定行数,或者传入一个行号的列表None
nrows读取前 N 行数据None
na_values指定哪些值应视为缺失值(NaN)None
skipfooter跳过文件结尾的指定行数0
encoding文件的编码格式(如 utf-8latin1 等)None

to_csv 常用参数:

参数说明默认值
path_or_bufferCSV 文件的路径或文件对象(支持文件路径、文件对象)必需参数
sep定义字段分隔符,默认是逗号(,),可以改为其他字符,如制表符(\t','
index是否写入行索引,默认 True 表示写入索引True
columns指定写入的列,可以是列的名称列表None
header是否写入列名,默认 True 表示写入列名,设置为 False 表示不写列名True
mode写入文件的模式,默认是 w(写模式),可以设置为 a(追加模式)'w'
encoding文件的编码格式,如 utf-8latin1None
line_terminator定义行结束符,默认为 \nNone
quoting设置如何对文件中的数据进行引号处理(0-3,具体引用方式可查文档)None
quotechar设置用于引用的字符,默认为双引号 "'"'
date_format自定义日期格式,如果列包含日期数据,则可以使用此参数指定日期格式None
doublequote如果为 True,则在写入时会将包含引号的文本使用双引号括起来True
import pandas as pd# 读取 CSV 文件,并自定义列名和分隔符
df = pd.read_csv('data.csv', sep=';', header=0, names=['A', 'B', 'C'], dtype={'A': int, 'B': float})
print(df)# 假设 df 是一个已有的 DataFrame
df.to_csv('output.csv', index=False, header=True, columns=['A', 'B'])
1.2:数据处理

在这里插入图片描述

2:Excel

操作方法说明
读取 Excel 文件pd.read_excel()读取 Excel 文件,返回 DataFrame
将 DataFrame 写入 ExcelDataFrame.to_excel()将 DataFrame 写入 Excel 文件
加载 Excel 文件pd.ExcelFile()加载 Excel 文件并访问多个表单
使用 ExcelWriter 写多个表单pd.ExcelWriter()写入多个 DataFrame 到同一 Excel 文件的不同表单
2.1:读取文件

读取excel方法的参数说明

参数描述
io这是必需的参数,指定了要读取的 Excel 文件的路径或文件对象。
sheet_name=0指定要读取的工作表名称或索引。默认为0,即第一个工作表。
header=0指定用作列名的行。默认为0,即第一行。
names=None用于指定列名的列表。如果提供,将覆盖文件中的列名。
index_col=None指定用作行索引的列。可以是列的名称或数字。
usecols=None指定要读取的列。可以是列名的列表或列索引的列表。
dtype=None指定列的数据类型。可以是字典格式,键为列名,值为数据类型。
engine=None指定解析引擎。默认为None,pandas 会自动选择。
converters=None用于转换数据的函数字典。
true_values=None指定应该被视为布尔值True的值。
false_values=None指定应该被视为布尔值False的值。
skiprows=None指定要跳过的行数或要跳过的行的列表。
nrows=None指定要读取的行数。
na_values=None指定应该被视为缺失值的值。
keep_default_na=True指定是否要将默认的缺失值(例如NaN)解析为NA。
na_filter=True指定是否要将数据转换为NA。
verbose=False指定是否要输出详细的进度信息。
parse_dates=False指定是否要解析日期。
date_parser=<no_default>用于解析日期的函数。
date_format=None指定日期的格式。
thousands=None指定千位分隔符。
decimal='.'指定小数点字符。
comment=None指定注释字符。
skipfooter=0指定要跳过的文件末尾的行数。
storage_options=None用于云存储的参数字典。
dtype_backend=<no_default>指定数据类型后端。
engine_kwargs=None传递给引擎的额外参数字典。
import pandas as pd# 读取默认的第一个表单
df = pd.read_excel('data.xlsx')
print(df)# 读取指定表单的内容(表单名称)
df = pd.read_excel('data.xlsx', sheet_name='Sheet1')
print(df)# 读取多个表单,返回一个字典
dfs = pd.read_excel('data.xlsx', sheet_name=['Sheet1', 'Sheet2'])
print(dfs)# 自定义列名并跳过前两行
df = pd.read_excel('data.xlsx', header=None, names=['A', 'B', 'C'], skiprows=2)
print(df)
2.2:写入文件

to_excel()方法的参数说明

参数描述
excel_writer这是必需的参数,指定了要写入的 Excel 文件路径或文件对象。
sheet_name='Sheet1'指定写入的工作表名称,默认为 ‘Sheet1’。
na_rep=''指定在 Excel 文件中表示缺失值(NaN)的字符串,默认为空字符串。
float_format=None指定浮点数的格式。如果为 None,则使用 Excel 的默认格式。
columns=None指定要写入的列。如果为 None,则写入所有列。
header=True指定是否写入列名作为第一行。如果为 False,则不写入列名。
index=True指定是否写入索引作为第一列。如果为 False,则不写入索引。
index_label=None指定索引列的标签。如果为 None,则不写入索引标签。
startrow=0指定开始写入的行号,默认从第0行开始。
startcol=0指定开始写入的列号,默认从第0列开始。
engine=None指定写入 Excel 文件时使用的引擎,默认为 None,pandas 会自动选择。
merge_cells=True指定是否合并单元格。如果为 True,则合并具有相同值的单元格。
inf_rep='inf'指定在 Excel 文件中表示无穷大值的字符串,默认为 ‘inf’。
freeze_panes=None指定冻结窗格的位置。如果为 None,则不冻结窗格。
storage_options=None用于云存储的参数字典。
engine_kwargs=None传递给引擎的额外参数字典。
import pandas as pd# 创建一个简单的 DataFrame
df = pd.DataFrame({
'Name': ['Alice', 'Bob', 'Charlie'],  # 第一列
'Age': [25, 30, 35], # 第二列
'City': ['New York', 'Los Angeles', 'Chicago'] # 第三列
})# 将 DataFrame 写入 Excel 文件,写入 'Sheet1' 表单
df.to_excel('output.xlsx', sheet_name='Sheet1', index=False)# 写入多个表单,使用 ExcelWriter
with pd.ExcelWriter('output2.xlsx') as writer:df.to_excel(writer, sheet_name='Sheet1', index=False)df.to_excel(writer, sheet_name='Sheet2', index=False)
2.3:加载文件

ExcelFile - 加载 Excel 文件

import pandas as pd# 使用 ExcelFile 加载 Excel 文件
excel_file = pd.ExcelFile('data.xlsx')# 查看所有表单的名称
print(excel_file.sheet_names)# 读取指定的表单
df = excel_file.parse('Sheet1')
print(df)# 关闭文件
excel_file.close()
2.4:多个表单的写入

可以使用ExcelWriter写入df到指定excel的指定sheet中

df1 = pd.DataFrame([["AAA", "BBB"]], columns=["Spam", "Egg"])  
df2 = pd.DataFrame([["ABC", "XYZ"]], columns=["Foo", "Bar"])  
with pd.ExcelWriter("path_to_file.xlsx") as writer:df1.to_excel(writer, sheet_name="Sheet1")  df2.to_excel(writer, sheet_name="Sheet2")

3:JSON

操作方法说明
从 JSON 文件/字符串读取数据pd.read_json()从 JSON 数据中读取并加载为 DataFrame
将 DataFrame 转换为 JSONDataFrame.to_json()将 DataFrame 转换为 JSON 格式的数据,可以指定结构化方式
支持 JSON 结构化方式orient 参数支持多种结构化方式,如 splitrecordscolumns
3.1:读取Json文件
import pandas as pddf = pd.read_json(path_or_buffer,      # JSON 文件路径、JSON 字符串或 URLorient=None,         # JSON 数据的结构方式,默认是 'columns'dtype=None,          # 强制指定列的数据类型convert_axes=True,   # 是否转换行列索引convert_dates=True,  # 是否将日期解析为日期类型keep_default_na=True # 是否保留默认的缺失值标记
)
rient 值JSON 格式示例描述
split{"index":["a","b"],"columns":["A","B"],"data":[[1,2],[3,4]]}使用键 indexcolumnsdata 结构
records[{"A":1,"B":2},{"A":3,"B":4}]每个记录是一个字典,表示一行数据
index{"a":{"A":1,"B":2},"b":{"A":3,"B":4}}使用索引为键,值为字典的方式
columns{"A":{"a":1,"b":3},"B":{"a":2,"b":4}}使用列名为键,值为字典的方式
values[[1,2],[3,4]]只返回数据,不包括索引和列名
3.2:DF读取为JSON
df.to_json(path_or_buffer=None,    # 输出的文件路径或文件对象,如果是 None 则返回 JSON 字符串orient=None,            # JSON 格式方式,支持 'split', 'records', 'index', 'columns', 'values'date_format=None,       # 日期格式,支持 'epoch', 'iso'default_handler=None,   # 自定义非标准类型的处理函数lines=False,            # 是否将每行数据作为一行(适用于 'records' 或 'split')encoding='utf-8'        # 编码格式
)

三:Pandas操作

1:基本方法

1.1:Series的基本方法
方法描述
axes返回行轴标签的列表
dtype返回对象的dtype。
empty如果Series为空,则返回True。
ndim根据定义返回基础数据的维数。
size返回基础数据中的元素数。
values将Series返回为ndarray。
head()返回前n行。
tail()返回最后n行。
import pandas as pd
import numpy as npif __name__ == '__main__':ser = pd.Series(np.random.randn(4))print(ser)print(ser.axes)  # 返回轴标签的列表 [RangeIndex(start=0, stop=4, step=1)]print(ser.empty)  # 返回一个布尔值,判断该对象是否为空, 值为falseprint(ser.ndim)  # 返回维度,值为1print(ser.size)  # 返回元素个数,值为4print(ser.values) # 返回数组,值为[-0.37214805  0.35749305 -0.11696405  0.11696405]print(ser.head()) # 默认返回前5行数据,可以自定义数据print(ser.tail()) # 默认返回最后5行数据,可以自定义数据
1.2:DataFrame的基本方法
属性/方法描述
T行和列互相转换
axes返回以行轴标签和列轴标签为唯一成员的列表。
dtypes返回此对象中的dtypes。
empty如果NDFrame完全为空[没有项目],则为true;否则为false。如果任何轴的长度为0。
ndim轴数/数组尺寸。
shape返回表示DataFrame维度的元组。
sizeNDFrame中的元素数。
valuesNDFrame的数字表示。
head()返回前n行。
tail()返回最后n行。
import pandas as pd
import numpy as npif __name__ == '__main__':d = {'Name': pd.Series(['A', 'B', 'C', 'D', 'E', 'F', 'G']),'Age': pd.Series([25, 26, 25, 23, 30, 29, 23]),'Rating': pd.Series([4.23, 3.24, 3.98, 2.56, 3.20, 4.6, 3.8])}# 创建一个 DataFramedf = pd.DataFrame(d)print(df)print("数据序列的转置是:")print(df.T)print("行轴标签和列轴标签是:")print(df.axes)print("每列的数据类型如下:")print(df.dtypes)print("Is the object empty?")print(df.empty)print("The dimension of the object is:")print(df.ndim)print("The shape of the object is:")print(df.shape)print("The total number of elements in our object is:")print(df.size)print("The actual data in our data frame is:")print(df.values)print("The first two rows of the data frame is:")print(df.head(2))print("The last two rows of the data frame is:")print(df.tail(2))
  Name  Age  Rating
0    A   25    4.23
1    B   26    3.24
2    C   25    3.98
3    D   23    2.56
4    E   30    3.20
5    F   29    4.60
6    G   23    3.80
数据序列的转置是:0     1     2     3    4    5    6
Name       A     B     C     D    E    F    G
Age       25    26    25    23   30   29   23
Rating  4.23  3.24  3.98  2.56  3.2  4.6  3.8
行轴标签和列轴标签是:
[RangeIndex(start=0, stop=7, step=1), Index(['Name', 'Age', 'Rating'], dtype='object')]
每列的数据类型如下:
Name       object
Age         int64
Rating    float64
dtype: object
Is the object empty?
False
The dimension of the object is:
2
The shape of the object is:
(7, 3)
The total number of elements in our object is:
21
The actual data in our data frame is:
[['A' 25 4.23]['B' 26 3.24]['C' 25 3.98]['D' 23 2.56]['E' 30 3.2]['F' 29 4.6]['G' 23 3.8]]
The first two rows of the data frame is:Name  Age  Rating
0    A   25    4.23
1    B   26    3.24
The last two rows of the data frame is:Name  Age  Rating
5    F   29     4.6
6    G   23     3.8

2:描述性统计

DataFrame用在大量的计算描述性信息统计和其他相关操作。其中大多数是聚合,例如sum(),mean()

一般而言,这些方法采用轴参数,就像ndarray。{sum,std,…}一样,但是可以通过名称或整数指定轴

1.1:sum()

返回所请求轴的值之和。默认情况下,轴为索引(轴=0)

import pandas as pd
import numpy as npd = {'Name':pd.Series(['A','B','C','D','E','F','G', 'H','I','J','K','L']),'Age':pd.Series([25,26,25,23,30,29,23,34,40,30,51,46]),'Rating':pd.Series([4.23,3.24,3.98,2.56,3.20,4.6,3.8,3.78,2.98,4.80,4.10,3.65])}# 字典series -> dataframe
df = pd.DataFrame(d)# 根据索引求和
print(df.sum())print(df)
/Users/cuihaida/project/python/first/venv/bin/python /Users/cuihaida/project/python/first/my-data-anaylze/my_pandas03.py 
Name      ABCDEFGHIJKL
Age                382
Rating           44.92
dtype: objectName  Age  Rating
0     A   25    4.23
1     B   26    3.24
2     C   25    3.98
3     D   23    2.56
4     E   30    3.20
5     F   29    4.60
6     G   23    3.80
7     H   34    3.78
8     I   40    2.98
9     J   30    4.80
10    K   51    4.10
11    L   46    3.65Process finished with exit code 0
1.2:mean()

返回平均值

import pandas as pd
import numpy as npd = {'Name':pd.Series(['A','B','C','D','E','F','G', 'H','I','J','K','L']),'Age':pd.Series([25,26,25,23,30,29,23,34,40,30,51,46]),'Rating':pd.Series([4.23,3.24,3.98,2.56,3.20,4.6,3.8,3.78,2.98,4.80,4.10,3.65])}# 字典series -> dataframe
df = pd.DataFrame(d)# 根据索引求和
print(df.sum())
print("=" * 20)
print(df.sum(axis=1, numeric_only=True))  # age + rating
print("=" * 20)# 返回平均值
print(df.mean(axis=0, skipna=True, numeric_only=True))
print("=" * 20)
print(df)
/Users/cuihaida/project/python/first/venv/bin/python /Users/cuihaida/project/python/first/my-data-anaylze/my_pandas03.py 
Name      ABCDEFGHIJKL
Age                382
Rating           44.92
dtype: object
====================
0     29.23
1     29.24
2     28.98
3     25.56
4     33.20
5     33.60
6     26.80
7     37.78
8     42.98
9     34.80
10    55.10
11    49.65
dtype: float64
====================
Age       31.833333
Rating     3.743333
dtype: float64
====================Name  Age  Rating
0     A   25    4.23
1     B   26    3.24
2     C   25    3.98
3     D   23    2.56
4     E   30    3.20
5     F   29    4.60
6     G   23    3.80
7     H   34    3.78
8     I   40    2.98
9     J   30    4.80
10    K   51    4.10
11    L   46    3.65Process finished with exit code 0
1.3:其他统计性函数
编号方法描述
1count()非空数
2sum()总数
3mean()平均数
4median()中位数
5mode()模式
6std()标准差
7min()最低值
8max()最大值
9abs()绝对值
10prod()乘积
11cumsum()累加
12cumprod()累乘

由于DataFrame是异构数据结构。泛型运算并不适用于所有功能,注意下面两点:

  • 诸如sum(),cumsum()之类的函数可用于数字和字符(或)字符串数据元素,而不会出现任何错误。虽然字符集合从不普遍使用,但不会抛出任何异常。
  • 当DataFrame包含字符或字符串数据时,诸如abs(),cumprod()之类的函数将引发异常,因为此类操作无法执行。
1.4:汇总函数describe

此函数提供平均值,std和IQR值。并且,函数不包括字符列和有关数字列的给定摘要

同时这个函数还支持一个include参数,用于传递有关汇总时需要考虑哪些列的必要信息的参数。取值列表;默认情况下为“数字”。

  • object − 汇总字符串列
  • number − 汇总数字列
  • all − 总结所有列在一起(不应该把它作为一个列表值)
import pandas as pd
import numpy as npif __name__ == '__main__':d = {'Name': pd.Series(['A', 'B', 'C', 'D', 'E', 'F', 'G']),'Age': pd.Series([25, 26, 25, 23, 30, 29, 23]),'Rating': pd.Series([4.23, 3.24, 3.98, 2.56, 3.20, 4.6, 3.8])}df = pd.DataFrame(d)# 查看数据集的描述信息, include -> object,number,all# object -> object类型的数据, 就是字符串列# number -> 数值列, 默认# all -> 所有列print(df.describe(include=['number']))

3:函数的应用

要将您自己或其他库的函数应用于Pandas对象,您应该了解三个重要的方法:

  • 表函数应用程序:pipe()
  • 行或列函数应用程序:apply()
  • 元素级函数应用程序:applymap()

要使用的适当方法取决于您的函数是希望对整个数据帧进行操作,还是行操作还是按列操作,还是按元素操作

3.1:表函数应用程序

可以通过传递函数和适当数量的参数作为管道参数来执行对DataFrame自定义操作,使用的方法是pipe()

import pandas as pd
import numpy as np# 定义一个操作函数,到时候会让dataFrame应用这个函数
def adder(ele1, ele2):return ele1 + ele2df = pd.DataFrame(np.random.randn(5,3),columns=['col1','col2','col3'])
print(df)
print("=" * 20)
ans = df.pipe(adder, 2) # 使用pipe()进行表函数应用, 对每一个元素 + 2
print(ans)
       col1      col2      col3
0 -1.743730  0.426996 -3.014761
1  0.209032 -0.407826  2.828854
2 -0.019639  0.879595  1.143649
3  0.155613 -0.562366 -3.301372
4  1.005468 -0.673557 -0.449234
====================col1      col2      col3
0  0.256270  2.426996 -1.014761
1  2.209032  1.592174  4.828854
2  1.980361  2.879595  3.143649
3  2.155613  1.437634 -1.301372
4  3.005468  1.326443  1.550766
3.2:行或列函数应用程序

可以使用apply()方法沿DataFrame或Panel的轴应用任意函数,该方法与描述性统计方法一样,采用可选的axis参数

默认情况下,该操作按列执行,将每一列视为类似数组的形式。

import pandas as pd
import numpy as np# 定义一个操作函数,到时候会让dataFrame应用这个函数
def adder(ele1,ele2):return ele1+ele2df = pd.DataFrame(np.random.randn(5,3),columns=['col1','col2','col3'])
print(df)
print(df.apply(np.mean)) # 列求平均
print(df.apply(np.mean,axis=1)) # 行求平均
       col1      col2      col3
0 -0.123136 -0.512380 -0.258701
1  0.775471 -0.783096 -0.580526
2 -0.994060 -0.593498 -0.293823
3 -1.039347  0.523736 -0.062395
4 -0.378043 -0.651012 -0.509351
col1   -0.351823
col2   -0.403250
col3   -0.340959
dtype: float64
0   -0.298073
1   -0.196050
2   -0.627127
3   -0.192669
4   -0.512802
dtype: float64
3.3:元素级函数应用程序

并非所有函数都可以向量化(NumPy数组既不返回另一个数组,也不返回任何值)

DataFrame上的applymap() 方法和Series上的map() 类似地接受任何采用单个值并返回单个值的Python函数。

import pandas as pd
import numpy as npdf = pd.DataFrame(np.random.randn(5, 3), columns=['col1', 'col2', 'col3'])
# 自定义函数
print(df)
print("=" * 20)
print(df['col1'].map(lambda x: x + 100)) # 对col1列的每一个数进行加1操作,不会影响原数组
       col1      col2      col3
0  0.720981 -1.848660 -1.021995
1 -0.263746  0.328287 -1.218116
2 -0.041258  0.364516 -0.553747
3 -0.772308  0.542454 -0.385765
4 -1.347373 -0.311151  0.608969
====================
0    100.720981
1     99.736254
2     99.958742
3     99.227692
4     98.652627
Name: col1, dtype: float64

4:重建索引

4.1:reindex()

重建索引 会更改DataFrame的行标签和列标签。重新索引是指使数据与特定轴上的一组给定标签匹配。

通过索引可以完成多个操作,例如:

  • 重新排序现有数据以匹配一组新标签。

  • 在标签数据不存在的标签位置中插入缺失值(NA)标记。

import pandas as pd
import numpy as np
N=20
df = pd.DataFrame({'A': pd.date_range(start='2016-01-01',periods=N,freq='D'),'x': np.linspace(0,stop=N-1,num=N),'y': np.random.rand(N),'C': np.random.choice(['Low','Medium','High'],N).tolist(),'D': np.random.normal(100, 10, size=(N)).tolist()
})# DataFrame重建索引
# 找出df中的A, C, B列作为新的索引和列, 对于在df中不存在的列,默认填充NaN
df_reindexed = df.reindex(index=[0,2,5], columns=['A', 'C', 'B'])
print(df_reindexed)
           A       C   B
0 2016-01-01  Medium NaN
2 2016-01-03     Low NaN
5 2016-01-06     Low NaN
4.2:reindex_like()

可以使用reindex_like()重新索引以与其他对象对齐

import pandas as pd
import numpy as npdef test2():df1 = pd.DataFrame(np.random.randn(10, 3), columns=['col1', 'col2', 'col3'])df2 = pd.DataFrame(np.random.randn(7, 3), columns=['col1', 'col2', 'col3'])df1 = df1.reindex_like(df2) # df1变成df2的索引和列的结构,也是7行3列,如果多出来就切断,如果少,就填充NaNprint(df1)if __name__ == '__main__':test2()
       col1      col2      col3
0 -0.224233  1.808778  0.105156
1 -0.729603  0.874080  0.470185
2 -1.795519  0.289359 -1.302235
3 -1.007448 -0.064831 -0.150167
4  0.694548  0.283895  0.574875
5  0.410779 -1.394223  0.376044
6 -0.447436  1.297874  0.764893

🎉 当然可以不填充NaN, 可以通过给reindex() & reindex_like()赋值method属性,决定填充信息

  • pad/ffill − 向前填充值
  • bfill/backfill − 向后填充值
  • nearest − 从最接近的索引值填充

🎉 在指定填充信息之后,还可以使用limit属性决定最多填充几行

import pandas as pd
import numpy as npdef test3():df1 = pd.DataFrame(np.random.randn(6, 3), columns=['col1', 'col2', 'col3'])df2 = pd.DataFrame(np.random.randn(2, 3), columns=['col1', 'col2', 'col3'])# 填充 NANprint(df2.reindex_like(df1))# 现在用前面的值填充NANprint("带前向填充的数据帧:")print(df2.reindex_like(df1, method='ffill'), limit=2) # 向前填充,最多填充2行if __name__ == '__main__':test3()
       col1      col2     col3
0  0.342667  0.725107 -0.40085
1 -0.346052  0.070069 -0.03319
2       NaN       NaN      NaN
3       NaN       NaN      NaN
4       NaN       NaN      NaN
5       NaN       NaN      NaN
带前向填充的数据帧:col1      col2     col3
0  0.342667  0.725107 -0.40085
1 -0.346052  0.070069 -0.03319
2 -0.346052  0.070069 -0.03319
3 -0.346052  0.070069 -0.03319
4       NaN       NaN      NaN
5       NaN       NaN      NaN
4.3:重命名

通过rename()方法,您可以基于某些映射(字典或系列)或任意函数来重新标记轴

import pandas as pd
import numpy as npdef test4():df1 = pd.DataFrame(np.random.randn(6, 3), columns=['col1', 'col2', 'col3'])print(df1)print("重命名行和列之后:")new = df1.rename(columns={'col1': 'c1', 'col2': 'c2'}, index={0: 'foo', 1: 'bar'})print(new)if __name__ == '__main__':test4()
       col1      col2      col3
0  1.985762  1.067307 -0.681527
1  0.240389  0.700743  0.051090
2 -1.677559  0.175037  0.242483
3  0.623115 -0.200200  0.216992
4  2.097055 -1.563505 -0.156450
5  0.672499  0.088381 -0.601609
重命名行和列之后:c1        c2      col3
foo  1.985762  1.067307 -0.681527
bar  0.240389  0.700743  0.051090
2   -1.677559  0.175037  0.242483
3    0.623115 -0.200200  0.216992
4    2.097055 -1.563505 -0.156450
5    0.672499  0.088381 -0.601609

5:迭代和排序

5.1:迭代

在这里插入图片描述

5.2:排序

核心就是sort_index()sort_values()

import numpy as np
import pandas as pddef test1():# 定义一个10行两列的dataframe, index表示每一行的索引,columns表示每一列的keyunsorted_df = pd.DataFrame(np.random.randn(10, 2), index=[1, 4, 6, 2, 3, 5, 9, 8, 0, 7], columns = ['col2', 'col1'])print(unsorted_df)print("默认排序")print(unsorted_df.sort_index()) # 排序, 默认根据index的升序排序(index从0 -> 9)print("可以使用ascending参数控制倒排")print(unsorted_df.sort_index(ascending=False))  # 倒排, index从9 -> 0print("也可以对列进行排序, 可以通过指定axis = 1")print(unsorted_df.sort_index(axis=1))print("可以使用 sort_values() 对值进行排序, by属性是通过那个key, 可以指定多个,列表形式")print(unsorted_df.sort_values(by='col1'))print("sort_values() 提供了从mergesort归并排序,heapsort堆排序和quicksort快排中选择算法的指定")print("mergesort是唯一稳定的排序")print(unsorted_df.sort_values(by='col1', kind='mergesort'))if __name__ == '__main__':test1()
/Users/cuihaida/project/python/first/venv/bin/python /Users/cuihaida/project/python/first/my-data-anaylze/my_pandas04.py col2      col1
1  0.071396 -1.011856
4 -0.218280  0.530760
6 -0.206268  0.562001
2 -0.385724  2.792641
3 -0.294598 -0.322529
5 -0.212050  0.278547
9  0.375532 -0.281603
8  0.690356  1.799434
0 -0.974060 -1.411210
7  0.502817  0.433678
默认排序col2      col1
0 -0.974060 -1.411210
1  0.071396 -1.011856
2 -0.385724  2.792641
3 -0.294598 -0.322529
4 -0.218280  0.530760
5 -0.212050  0.278547
6 -0.206268  0.562001
7  0.502817  0.433678
8  0.690356  1.799434
9  0.375532 -0.281603
可以使用ascending参数控制倒排col2      col1
9  0.375532 -0.281603
8  0.690356  1.799434
7  0.502817  0.433678
6 -0.206268  0.562001
5 -0.212050  0.278547
4 -0.218280  0.530760
3 -0.294598 -0.322529
2 -0.385724  2.792641
1  0.071396 -1.011856
0 -0.974060 -1.411210
也可以对列进行排序, 可以通过指定axis = 1col1      col2
1 -1.011856  0.071396
4  0.530760 -0.218280
6  0.562001 -0.206268
2  2.792641 -0.385724
3 -0.322529 -0.294598
5  0.278547 -0.212050
9 -0.281603  0.375532
8  1.799434  0.690356
0 -1.411210 -0.974060
7  0.433678  0.502817
可以使用 sort_values() 对值进行排序, by属性是通过那个key, 可以指定多个,列表形式col2      col1
0 -0.974060 -1.411210
1  0.071396 -1.011856
3 -0.294598 -0.322529
9  0.375532 -0.281603
5 -0.212050  0.278547
7  0.502817  0.433678
4 -0.218280  0.530760
6 -0.206268  0.562001
8  0.690356  1.799434
2 -0.385724  2.792641
sort_values() 提供了从mergesort归并排序,heapsort堆排序和quicksort快排中选择算法的指定
mergesort是唯一稳定的排序col2      col1
0 -0.974060 -1.411210
1  0.071396 -1.011856
3 -0.294598 -0.322529
9  0.375532 -0.281603
5 -0.212050  0.278547
7  0.502817  0.433678
4 -0.218280  0.530760
6 -0.206268  0.562001
8  0.690356  1.799434
2 -0.385724  2.792641Process finished with exit code 0

6:series的文本处理

几乎所有这些方法都可用于Python字符串函数

因此,将Series对象转换为String对象,然后执行该操作。

方法说明
lower()将系列/索引中的字符串转换为小写。
upper()将系列/索引中的字符串转换为大写。
len()计算字符串length()。
strip()帮助从两侧从系列/索引中的每个字符串中去除空格(包括换行符)。
split(' ')用给定的模式分割每个字符串。
cat(sep=' ')用给定的分隔符连接系列/索引元素。
get_dummies()返回具有一键编码值的DataFrame。
contains(pattern)如果子字符串包含在元素中,则为每个元素返回一个布尔值True,否则返回False。
replace(a,b)a值替换成b。
repeat(value)以指定的次数重复每个元素。
count(pattern)返回每个元素中模式出现的次数。
startswith(pattern)如果系列/索引中的元素以模式开头,则返回true。
endswith(pattern)如果系列/索引中的元素以模式结尾,则返回true。
find(pattern)返回模式首次出现的第一个位置。
findall(pattern)返回所有出现的模式的列表。
swapcase大小写互换
islower()检查“系列/索引”中每个字符串中的所有字符是否都小写。返回布尔值
isupper()检查“系列/索引”中每个字符串中的所有字符是否都大写。返回布尔值。
isnumeric()检查“系列/索引”中每个字符串中的所有字符是否都是数字。返回布尔值。
import numpy as np
import pandas as pddef test2():s = pd.Series(['Tom', 'William Rick', 'John', 'Alber@t', np.nan, '1234', 'SteveSmith'])print(s.str.len())print(s.str.lower())print(s.str.upper())if __name__ == '__main__':test2()

7:自定义选项的设置

在这里插入图片描述

import numpy as np
import pandas as pddef test3():# 查看可以展示的最大行数和列数print(pd.get_option("display.max_rows"))print(pd.get_option("display.max_columns"))  # 默认显示的列数是0, 表示显示所有列print("=" * 40)# 设置最大行数和列数pd.set_option("display.max_rows", 10)pd.set_option("display.max_columns", 10)  # 调整成为最多显示10列print(pd.get_option("display.max_rows"))print(pd.get_option("display.max_columns"))print("=" * 40)# 恢复默认pd.reset_option("display.max_rows")pd.reset_option("display.max_columns")print(pd.get_option("display.max_rows"))print(pd.get_option("display.max_columns"))print("=" * 40)# 查看描述print(pd.describe_option("display.max_rows"))print(pd.describe_option("display.max_columns"))print("=" * 40)# 临时设置,只在with块中生效with pd.option_context("display.max_rows", 10, "display.max_columns", 10):print(pd.get_option("display.max_rows"))  # 10print(pd.get_option("display.max_columns"))  # 10print("=" * 40)print(pd.get_option("display.max_rows")) # 60, 不受到option_context的设置的影响print(pd.get_option("display.max_columns")) # 10print("=" * 40)if __name__ == '__main__':test3()
60
0
========================================
10
10
========================================
60
0
========================================
display.max_rows : intIf max_rows is exceeded, switch to truncate view. Depending on`large_repr`, objects are either centrally truncated or printed asa summary view. 'None' value means unlimited.In case python/IPython is running in a terminal and `large_repr`equals 'truncate' this can be set to 0 and pandas will auto-detectthe height of the terminal and print a truncated object which fitsthe screen height. The IPython notebook, IPython qtconsole, orIDLE do not run in a terminal and hence it is not possible to docorrect auto-detection.[default: 60] [currently: 60]
None
display.max_columns : intIf max_cols is exceeded, switch to truncate view. Depending on`large_repr`, objects are either centrally truncated or printed asa summary view. 'None' value means unlimited.In case python/IPython is running in a terminal and `large_repr`equals 'truncate' this can be set to 0 or None and pandas will auto-detectthe width of the terminal and print a truncated object which fitsthe screen width. The IPython notebook, IPython qtconsole, or IDLEdo not run in a terminal and hence it is not possible to docorrect auto-detection and defaults to 20.[default: 0] [currently: 0]
None
========================================
10
10
========================================
60
0
========================================

8:索引和数据查询

Python和NumPy索引运算符“[]”和属性运算符“.”。可以在各种用例中快速轻松地访问Pandas数据结构

Pandas现在支持两种类型的多轴索引:下表中提到了三种类型:

索引说明
.loc()基于标签
.iloc()基于整数
8.1:loc

.loc() 具有多种访问方法,例如:

  • 一个标量标签
  • 标签列表
  • 切片对象
  • 布尔数组

loc 需要两个单/列表/范围运算符,以“,”分隔。第一个指示行,第二个指示列。

import pandas as pd
import numpy as npdef test1():df = pd.DataFrame(np.random.randn(8, 4),index=['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'],columns=['A', 'B', 'C', 'D'])  # 定义一个8行4列的DataFrame, 索引为a-h, 列名为A-Dprint(df)print("筛选出每一行的A列")print(df['A'])print("=" * 30)print(df.loc[:, 'A'])print("=" * 30)print("筛选出所有的AC列")print(df.loc[:, ['A', 'C']])print("=" * 30)print("同时可以指定行和列, 例如输出a, c, f行的A, C列")print(df.loc[['a', 'c', 'f'], ['A', 'C']])print("=" * 30)print("可以为所有的列指定行的范围,使用:")print(df.loc['a':'c', ['A', 'C']])print("=" * 30)if __name__ == '__main__':test1()
          A         B         C         D
a  1.382366 -1.163601  0.176177  0.672256
b -0.282480 -0.967808  0.930259  0.316234
c -0.043770  1.639644 -0.505511  1.421071
d  0.660928  0.612623  0.292144  1.240187
e  1.449997 -0.061115  0.104454  0.194620
f -1.048595 -0.017617  0.250532 -1.888130
g  0.856651  0.994930 -0.220943  1.727685
h -0.482508 -0.440425 -0.317698 -0.555271
筛选出每一行的A列
a    1.382366
b   -0.282480
c   -0.043770
d    0.660928
e    1.449997
f   -1.048595
g    0.856651
h   -0.482508
Name: A, dtype: float64
==============================
a    1.382366
b   -0.282480
c   -0.043770
d    0.660928
e    1.449997
f   -1.048595
g    0.856651
h   -0.482508
Name: A, dtype: float64
==============================
筛选出所有的AC列A         C
a  1.382366  0.176177
b -0.282480  0.930259
c -0.043770 -0.505511
d  0.660928  0.292144
e  1.449997  0.104454
f -1.048595  0.250532
g  0.856651 -0.220943
h -0.482508 -0.317698
==============================
同时可以指定行和列, 例如输出a, c, f行的A, C列A         C
a  1.382366  0.176177
c -0.043770 -0.505511
f -1.048595  0.250532
==============================
可以为所有的列指定行的范围,使用:A         C
a  1.382366  0.176177
b -0.282480  0.930259
c -0.043770 -0.505511
==============================
8.2:iloc

同理,只不过这个索引切片变成了整数

import pandas as pd
import numpy as npdef test2():df = pd.DataFrame(np.random.randn(8, 4),index=['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'],columns=['A', 'B', 'C', 'D'])print(df)print("=" * 30)print("df中的前4行是:")print(df.iloc[:4])print("=" * 30)print("df中的后4行是:")print(df.iloc[4:])print("=" * 30)print("df中的第2行和第4行是:")print(df.iloc[[1, 3]])print("=" * 30)print("df中的前4行的后两列是:")print(df.iloc[:4, 2:])print("=" * 30)print("df中的第2行和第4行,第2列和第4列是:")print(df.iloc[[1, 3], [1, 3]])print("=" * 30)if __name__ == '__main__':test2()
          A         B         C         D
a -0.343237 -0.155287 -0.713359  0.071921
b -0.165145  0.491577 -0.107699  1.016831
c -0.527483 -0.391398  0.700065  0.054806
d -2.306590  0.223241 -0.097838 -0.431856
e -1.398431 -0.267630  0.366289 -0.373675
f -0.446961 -1.622479 -0.319882 -0.999932
g  0.645857 -1.249595  0.513613 -0.140469
h  0.227319  0.543510  1.938501  1.312588
==============================
df中的前4行是:A         B         C         D
a -0.343237 -0.155287 -0.713359  0.071921
b -0.165145  0.491577 -0.107699  1.016831
c -0.527483 -0.391398  0.700065  0.054806
d -2.306590  0.223241 -0.097838 -0.431856
==============================
df中的后4行是:A         B         C         D
e -1.398431 -0.267630  0.366289 -0.373675
f -0.446961 -1.622479 -0.319882 -0.999932
g  0.645857 -1.249595  0.513613 -0.140469
h  0.227319  0.543510  1.938501  1.312588
==============================
df中的第2行和第4行是:A         B         C         D
b -0.165145  0.491577 -0.107699  1.016831
d -2.306590  0.223241 -0.097838 -0.431856
==============================
df中的前4行的后两列是:C         D
a -0.713359  0.071921
b -0.107699  1.016831
c  0.700065  0.054806
d -0.097838 -0.431856
==============================
df中的第2行和第4行,第2列和第4列是:B         D
b  0.491577  1.016831
d  0.223241 -0.431856
==============================

四:高级操作

1:缺失值处理

1.1:对于缺失值的表示
  • NaNfloat 类型的默认缺失标记(来自 NumPy)
  • Noneobject 类型的缺失标记(Python 内置)
  • NaT:时间类型(datetime64)的缺失值
1.2:对于缺失值的检测
df.isna()       # 返回布尔矩阵(True=缺失)
df.notna()      # 返回布尔矩阵(False=缺失)
df.isnull()     # isna() 的别名(功能相同)df.isna().sum()             # 每列缺失值数量
df.isna().sum().sum()       # 整个DataFrame缺失值总数
df.isna().mean() * 100      # 每列缺失值百分比
import numpy as np
import pandas as pddict = {'name': ['Tom', 'Nick', 'John'],'age': [20, 21, 19],'city': ['New York', 'Paris', None]
}df = pd.DataFrame(dict)print(df)
print("=" * 50)
print("布尔矩阵,如果是缺失值,将返回True, 否则是False")
print(df.isna())
print("=" * 50)
print("每列缺失值百分比")
print(df.isna().mean() * 100)
1.3:对于缺失值的删除
# 删除包含缺失值的行(默认)
df.dropna(axis=0)  # 删除包含缺失值的列
df.dropna(axis=1)  # 删除全为缺失值的行
df.dropna(how='all')  # 删除在特定列有缺失的行
df.dropna(subset=['col1', 'col2'])  # 保留至少有 n 个非缺失值的行
df.dropna(thresh=5)
1.4:对于缺失值的填充
# 可以固定值填充
df.fillna(0)  # 所有缺失值填充为0
df.fillna({'col1': 0, 'col2': 'unknown'})  # 按列指定填充值# 统计值填充
df.fillna(df.mean()) # 用各列均值填充
df['col1'].fillna(df['col1'].median(), inplace=True)  # 中位数填充(原地修改)# 前后填充
df.fillna(method='ffill')      # 用前一个有效值填充(向前填充)
df.fillna(method='bfill')      # 用后一个有效值填充(向后填充)
df.fillna(method='ffill', limit=2)  # 最多向前填充2个# 插值法填充
df.interpolate()               # 线性插值(默认)
df.interpolate(method='time')  # 时间索引插值
df.interpolate(method='polynomial', order=2)  # 二阶多项式插值
1.5:其他常用操作
# 将数值列的NaN替换为None(转换类型)
df['col'] = df['col'].where(pd.notnull(df['col']), None)# 按分组用组内均值填充
df.groupby('group_col').transform(lambda x: x.fillna(x.mean()))# 将占位符(如 -999)识别为缺失值
df.replace(-999, np.nan, inplace=True)

2:统计、分组和连接

Pandas核心操作
统计计算
分组操作
数据连接
描述性统计
相关性分析
分布分析
累积计算
分组聚合
分组转换
分组过滤
分组迭代
Merge合并
Join连接
Concatenate拼接
数据比较
高级技巧
透视表
交叉表
时间重采样
性能优化
2.1:统计计算

基础统计函数

import pandas as pd
import numpy as np# 创建示例数据
data = {'Product': ['A', 'B', 'C', 'D', 'E'],'Sales': [250, 300, 180, 400, np.nan],'Cost': [120, 150, 100, 220, 180],'Category': ['Electronics', 'Furniture', 'Electronics', 'Furniture', 'Office']
}
df = pd.DataFrame(data)# 基本统计信息
print("描述性统计:")
print(df.describe())# 特定统计计算
print("\n销售总额:", df['Sales'].sum())
print("平均成本:", df['Cost'].mean())
print("最大销售额:", df['Sales'].max())
print("销售额标准差:", df['Sales'].std())
print("非空值数量:", df['Sales'].count())

相关性的分析

import pandas as pd
import numpy as np# 创建示例数据
data = {'Product': ['A', 'B', 'C', 'D', 'E'],'Sales': [250, 300, 180, 400, np.nan],'Cost': [120, 150, 100, 220, 180],'Category': ['Electronics', 'Furniture', 'Electronics', 'Furniture', 'Office']
}
df = pd.DataFrame(data)# 添加利润列
df['Profit'] = df['Sales'] - df['Cost']# 计算相关性矩阵
correlation = df[['Sales', 'Cost', 'Profit']].corr()
print("\n相关性矩阵:")
print(correlation)# 单个相关性
print("\n销售与利润的相关性:", df['Sales'].corr(df['Profit']))

累积计算

import pandas as pd
import numpy as np# 创建示例数据
data = {'Product': ['A', 'B', 'C', 'D', 'E'],'Sales': [250, 300, 180, 400, np.nan],'Cost': [120, 150, 100, 220, 180],'Category': ['Electronics', 'Furniture', 'Electronics', 'Furniture', 'Office']
}
df = pd.DataFrame(data)# 累积计算
df['Cumulative_Sales'] = df['Sales'].cumsum()  # 累积求和, [250, 550, 730, 1130]
df['Running_Max'] = df['Sales'].cummax()  # 累积最大值, [250, 300, 300, 400]print("\n累积统计:")
print(df[['Product', 'Sales', 'Cumulative_Sales', 'Running_Max']])()print("\n累积统计:")
print(df[['Product', 'Sales', 'Cumulative_Sales', 'Running_Max']])

分布分析

import pandas as pd
import numpy as np# 创建示例数据
data = {'Product': ['A', 'B', 'C', 'D', 'E'],'Sales': [250, 300, 180, 400, np.nan],'Cost': [120, 150, 100, 220, 180],'Category': ['Electronics', 'Furniture', 'Electronics', 'Furniture', 'Office']
}
df = pd.DataFrame(data)# 值计数
print("\n类别分布:")
print(df['Category'].value_counts())# 分位数
print("\n销售额的25%分位数:", df['Sales'].quantile(0.25))
print("销售额的50%分位数:", df['Sales'].quantile(0.5))# 直方图分箱
print("\n销售额分布:")
print(pd.cut(df['Sales'], bins=3).value_counts())
2.2:分组操作

基础分组统计

import pandas as pd
import numpy as np# 创建示例数据
data = {'Product': ['A', 'B', 'C', 'D', 'E'],'Sales': [250, 300, 180, 400, np.nan],'Cost': [120, 150, 100, 220, 180],'Category': ['Electronics', 'Furniture', 'Electronics', 'Furniture', 'Office']
}
df = pd.DataFrame(data)
# 按类别分组并计算平均值
category_group = df.groupby('Category')
print("\n按类别分组平均值:")
print(category_group.mean(numeric_only=True))# 多列分组
multi_group = df.groupby(['Category', 'Product'])
print("\n多级分组总和:")
print(multi_group.sum(numeric_only=True))

聚合函数

import pandas as pd
import numpy as np# 创建示例数据
data = {'Product': ['A', 'B', 'C', 'D', 'E'],'Sales': [250, 300, 180, 400, np.nan],'Cost': [120, 150, 100, 220, 180],'Category': ['Electronics', 'Furniture', 'Electronics', 'Furniture', 'Office']
}
df = pd.DataFrame(data)
# 应用多个聚合函数
agg_results = category_group.agg({'Sales': ['sum', 'mean', 'max'],'Cost': ['min', 'median']
})
print("\n多聚合函数结果:")
print(agg_results)

分组转换

import pandas as pd
import numpy as np# 创建示例数据
data = {'Product': ['A', 'B', 'C', 'D', 'E'],'Sales': [250, 300, 180, 400, np.nan],'Cost': [120, 150, 100, 220, 180],'Category': ['Electronics', 'Furniture', 'Electronics', 'Furniture', 'Office']
}
df = pd.DataFrame(data)
# 计算组内标准化值
df['Z-Score'] = category_group['Sales'].transform(lambda x: (x - x.mean()) / x.std()
)# 填充组内平均值
df['Sales_Filled'] = category_group['Sales'].transform(lambda x: x.fillna(x.mean())
)print("\n分组转换结果:")
print(df[['Product', 'Category', 'Sales', 'Z-Score', 'Sales_Filled']])

分组过滤

import pandas as pd
import numpy as np# 创建示例数据
data = {'Product': ['A', 'B', 'C', 'D', 'E'],'Sales': [250, 300, 180, 400, np.nan],'Cost': [120, 150, 100, 220, 180],'Category': ['Electronics', 'Furniture', 'Electronics', 'Furniture', 'Office']
}
df = pd.DataFrame(data)# 过滤销售总额超过400的组
filtered_groups = category_group.filter(lambda x: x['Sales'].sum() > 400)
print("\n销售总额超过400的类别:")
print(filtered_groups)

分组迭代

import pandas as pd
import numpy as np# 创建示例数据
data = {'Product': ['A', 'B', 'C', 'D', 'E'],'Sales': [250, 300, 180, 400, np.nan],'Cost': [120, 150, 100, 220, 180],'Category': ['Electronics', 'Furniture', 'Electronics', 'Furniture', 'Office']
}
df = pd.DataFrame(data)category_group = df.groupby('Category')print("\n分组迭代:")
for name, group in category_group:print(f"\n类别: {name}")print(group[['Product', 'Sales']])
2.3:数据连接

合并 (Merge)

# 创建第二个DataFrame
inventory = pd.DataFrame({'Product': ['A', 'B', 'C', 'F'],'Stock': [15, 8, 20, 12],'Warehouse': ['NY', 'CA', 'TX', 'FL']
})# 内连接
inner_merge = pd.merge(df, inventory, on='Product', how='inner')
print("\n内连接结果:")
print(inner_merge)# 左连接
left_merge = pd.merge(df, inventory, on='Product', how='left')
print("\n左连接结果:")
print(left_merge)# 指定不同列名
prices = pd.DataFrame({'Item': ['A', 'B', 'C', 'D', 'E'],'Price': [99, 149, 79, 199, 129]
})
different_cols = pd.merge(df, prices, left_on='Product', right_on='Item')
print("\n不同列名连接:")
print(different_cols[['Product', 'Sales', 'Price']])

连接 (Join)

# 设置索引
df_indexed = df.set_index('Product')
inventory_indexed = inventory.set_index('Product')# 索引连接
joined = df_indexed.join(inventory_indexed, how='left')
print("\n索引连接结果:")
print(joined)

拼接 (Concatenate)

# 创建新数据
new_products = pd.DataFrame({'Product': ['F', 'G'],'Sales': [320, 280],'Cost': [150, 130],'Category': ['Electronics', 'Office']
})# 垂直拼接
vertical_concat = pd.concat([df, new_products], ignore_index=True)
print("\n垂直拼接结果:")
print(vertical_concat)# 水平拼接
additional_info = pd.DataFrame({'Product': ['A', 'B', 'C', 'D', 'E'],'Rating': [4.5, 4.2, 4.8, 4.0, 4.6]
})
horizontal_concat = pd.concat([df, additional_info.set_index('Product')], axis=1)
print("\n水平拼接结果:")
print(horizontal_concat)

比较与组合

# 比较数据集
comparison = df.compare(new_products)
print("\n数据集比较:")
print(comparison)# 组合数据
combine_first = df.set_index('Product').combine_first(new_products.set_index('Product')
)
print("\n组合数据结果:")
print(combine_first)
2.4:高级技巧

数据透视表

# 创建透视表
pivot_table = pd.pivot_table(df, values='Sales', index='Category', columns=pd.cut(df['Cost'], bins=[0, 150, 250]), aggfunc=['sum', 'mean'],fill_value=0
)
print("\n数据透视表:")
print(pivot_table)

交叉表

# 创建交叉表
cross_tab = pd.crosstab(df['Category'], pd.cut(df['Cost'], bins=[0, 150, 250]),values=df['Sales'], aggfunc='mean'
)
print("\n交叉表:")
print(cross_tab)

分组时间序列重采样

# 创建时间序列数据
date_rng = pd.date_range(start='2023-01-01', end='2023-01-10', freq='D')
time_series = pd.DataFrame({'Date': date_rng,'Sales': np.random.randint(100, 500, size=(len(date_rng))),'Category': np.random.choice(['Electronics', 'Furniture', 'Office'], size=len(date_rng))
})# 按类别分组并重采样
time_series.set_index('Date', inplace=True)
resampled = time_series.groupby('Category').resample('3D').sum()
print("\n时间序列重采样:")
print(resampled)

3:日期相关操作

3.1:日期的创建和转换

创建时间戳

ts = pd.Timestamp("2023-08-15 14:30:00")
print("单个时间戳", ts)# 时间范围, periods -> 个数, freq -> 时间间隔,D-天,H-小时,M-分钟,S-秒
date_range = pd.date_range('2023-01-01', periods=5, freq='D')
print("\n日期范围:", date_range)# 工作日范围(bdate)
bdate_range = pd.bdate_range('2023-08-01', periods=5)
print("\n工作日范围:", bdate_range)

转换数据类型

# 从字符串转换
dates = ['2023-01-01', '2023-02-15', '2023-03-22']
df = pd.DataFrame({'date_str': dates})
df['date_dt'] = pd.to_datetime(df['date_str'])
print("\n字符串转日期:\n", df)# 从不同格式转换
euro_dates = ['15/08/2023', '20/09/2023', '05/11/2023']
df['euro_date'] = pd.to_datetime(euro_dates, format='%d/%m/%Y')
print("\n欧洲格式日期:\n", df)# 处理错误日期
mixed_dates = ['2023-01-01', 'invalid', '2023-03-22', '2023-02-30']
df = pd.DataFrame({'date': mixed_dates})
df['converted'] = pd.to_datetime(df['date'], errors='coerce')
print("\n错误处理转换:\n", df)
3.2:日期时间属性提取

dt.year/month/day/…

基本属性的提取

# 创建时间序列数据
dates = pd.date_range('2023-01-01', periods=10, freq='D')
df = pd.DataFrame({'date': dates})# 提取日期组件
df['year'] = df['date'].dt.year
df['month'] = df['date'].dt.month
df['day'] = df['date'].dt.day
df['dayofweek'] = df['date'].dt.dayofweek  # 周一=0, 周日=6
df['day_name'] = df['date'].dt.day_name()
df['is_weekend'] = df['date'].dt.dayofweek >= 5print("\n日期属性提取:\n", df.head())

时间属性的提取

# 创建带时间的数据
times = pd.date_range('2023-01-01 08:00', periods=5, freq='4H')
df = pd.DataFrame({'datetime': times})# 提取时间组件
df['hour'] = df['datetime'].dt.hour
df['minute'] = df['datetime'].dt.minute
df['second'] = df['datetime'].dt.second
df['time'] = df['datetime'].dt.time
df['period'] = pd.cut(df['hour'], bins=[0, 6, 12, 18, 24], labels=['Night', 'Morning', 'Afternoon', 'Evening'])print("\n时间属性提取:\n", df)
3.3:日期时间运算

时间差的计算

# 创建时间差
td1 = pd.Timedelta(days=5, hours=3)
print("\n时间差:", td1)# 时间运算
start = pd.Timestamp('2023-01-01')
end = start + pd.Timedelta(weeks=2)
print("开始日期:", start)
print("结束日期:", end)
print("时间差:", end - start)# 序列运算
dates = pd.date_range('2023-01-01', periods=5, freq='2D')
df = pd.DataFrame({'date': dates})
df['next_date'] = df['date'] + pd.Timedelta(days=1)
df['days_diff'] = (df['next_date'] - df['date']).dt.daysprint("\n时间差计算:\n", df)

日期的偏移

from pandas.tseries.offsets import *# 基本偏移
date = pd.Timestamp('2023-08-15')
print("\n原始日期:", date)
print("加3天:", date + DateOffset(days=3))
print("加2个月:", date + DateOffset(months=2))# 工作日偏移
print("下个工作日:", date + BDay())
print("下个月第一个工作日:", date + BMonthBegin())# 特殊偏移
print("季度末:", date + BQuarterEnd())
print("财年末(3月):", date + FY5253Quarter(quarter=4, startingMonth=3, variation="nearest"))
3.4:时间序列操作

重新采样

# 创建时间序列数据
date_rng = pd.date_range('2023-01-01', '2023-01-10', freq='8H')
data = np.random.randint(0, 100, size=(len(date_rng)))
ts = pd.Series(data, index=date_rng)# 降采样 (低频)
daily_mean = ts.resample('D').mean()
daily_max = ts.resample('D').max()
print("\n按天重采样(均值):\n", daily_mean)
print("\n按天重采样(最大值):\n", daily_max)# 升采样 (高频)
upsampled = ts.resample('2H').asfreq()  # 插入NaN
ffilled = ts.resample('2H').ffill()     # 向前填充
print("\n升采样(插入NaN):\n", upsampled.head(10))
print("\n升采样(向前填充):\n", ffilled.head(10))# OHLC重采样
ohlc = ts.resample('D').ohlc()
print("\nOHLC重采样:\n", ohlc)

滚动窗口的计算

# 创建时间序列
data = np.random.randn(100)
index = pd.date_range('2023-01-01', periods=100, freq='D')
ts = pd.Series(data, index=index)# 滚动计算
rolling_mean = ts.rolling(window=7).mean()
rolling_std = ts.rolling(window=14).std()
expanding_mean = ts.expanding().mean()# 组合计算
df = pd.DataFrame({'value': ts,'7d_mean': rolling_mean,'14d_std': rolling_std,'exp_mean': expanding_mean
})
print("\n滚动窗口计算(前10行):\n", df.head(10))# 带偏移的滚动窗口
offset_mean = ts.rolling(window='30D').mean()  # 30天滚动平均
print("\n时间偏移滚动窗口:\n", offset_mean.head(10))
3.5:日期索引操作

时间索引切片

# 创建时间序列数据
data = np.random.randn(100)
index = pd.date_range('2023-01-01', periods=100, freq='D')
ts = pd.Series(data, index=index)# 基础切片
print("1月数据:\n", ts['2023-01'])
print("\n1月15日至1月20日:\n", ts['2023-01-15':'2023-01-20'])# 部分日期字符串切片
print("\n所有1月15日数据:\n", ts[ts.index.day == 15])# 时间范围切片
print("\n1月1日到3月1日:\n", ts['2023-01-01':'2023-03-01'])

时间索引操作

# 设置时间索引
df = pd.DataFrame({'value': np.random.randn(100),'date': pd.date_range('2023-01-01', periods=100, freq='D')
})
df.set_index('date', inplace=True)# 按时间组件选择
print("所有周一数据:\n", df[df.index.dayofweek == 0].head())# 按时间范围选择
print("\n工作时间数据(9AM-5PM):\n", df.between_time('09:00', '17:00'))# 按日期类型选择
print("\n月初数据:\n", df[df.index.is_month_start])
print("\n季度末数据:\n", df[df.index.is_quarter_end])
3.6:其他常用操作

时区的处理

# 创建时区无关时间
date_rng = pd.date_range('2023-01-01 00:00', periods=3, freq='8H')
ts = pd.Series(range(3), index=date_rng)# 添加时区
ts_utc = ts.tz_localize('UTC')
print("\nUTC时间:\n", ts_utc)# 时区转换
ts_ny = ts_utc.tz_convert('America/New_York')
print("\n纽约时间:\n", ts_ny)# 处理夏令时
dst_range = pd.date_range('2023-03-12 00:00', periods=5, freq='H', tz='America/New_York')
print("\n夏令时转换:\n", dst_range)

节假日日历

from pandas.tseries.holiday import USFederalHolidayCalendar# 创建美国节假日日历
cal = USFederalHolidayCalendar()
holidays = cal.holidays(start='2023-01-01', end='2023-12-31')
print("2023年美国联邦节假日:\n", holidays)# 工作日计算
bday_us = pd.offsets.CustomBusinessDay(calendar=USFederalHolidayCalendar())
date = pd.Timestamp('2023-12-24')  # 圣诞节前
print("\n2023-12-24后的第一个工作日:", date + bday_us)# 自定义节假日
class MyCalendar(AbstractHolidayCalendar):rules = [Holiday('My Birthday', month=8, day=15),Holiday('Company Founding', month=11, day=1)]my_cal = MyCalendar()
my_holidays = my_cal.holidays(start='2023-01-01', end='2023-12-31')
print("\n自定义节假日:\n", my_holidays)

时间序列分析

# 创建带趋势和季节性的时间序列
np.random.seed(42)
t = np.arange(100)
trend = 0.1 * t
seasonality = 5 * np.sin(2 * np.pi * t / 30)
noise = np.random.normal(0, 1, 100)
data = trend + seasonality + noiseindex = pd.date_range('2023-01-01', periods=100, freq='D')
ts = pd.Series(data, index=index)# 分解时间序列
from statsmodels.tsa.seasonal import seasonal_decompose
decomposed = seasonal_decompose(ts, model='additive', period=30)# 创建包含组件的DataFrame
df_decomposed = pd.DataFrame({'observed': decomposed.observed,'trend': decomposed.trend,'seasonal': decomposed.seasonal,'residual': decomposed.resid
})print("\n时间序列分解(前5行):\n", df_decomposed.head())

时间序列的存储

# 高效存储时间序列
df = pd.DataFrame({'timestamp': pd.date_range('2023-01-01', periods=1000, freq='T'),'value': np.random.randn(1000)
})# 优化数据类型
df['timestamp'] = df['timestamp'].astype('datetime64[s]')  # 精确到秒
print("\n优化前内存:", df.memory_usage(deep=True).sum())
df['value'] = df['value'].astype('float32')
print("优化后内存:", df.memory_usage(deep=True).sum())# 使用Period表示时间区间
df['period'] = df['timestamp'].dt.to_period('D')
print("\n周期表示:\n", df[['timestamp', 'period']].head())

大型的时间序列处理

# 创建大型时间序列
size = 10**6  # 100万行
big_ts = pd.Series(np.random.randn(size),index=pd.date_range('2020-01-01', periods=size, freq='S')
)# 高效重采样
%timeit big_ts.resample('1T').mean()  # 原始方法# 使用Grouper优化
%timeit big_ts.groupby(pd.Grouper(freq='1T')).mean()# 下采样优化
%timeit big_ts.loc[big_ts.index.min():big_ts.index.max():'5T']  # 步长选择
3.7:完整实际实例演示
import numpy as np
import pandas as pd
from pandas.tseries.holiday import USFederalHolidayCalendar
from statsmodels.tsa.seasonal import seasonal_decompose# 创建销售数据集
np.random.seed(42)
dates = pd.date_range('2023-01-01', '2023-06-30', freq='D')
sales = np.random.randint(50, 200, size=len(dates))
weekday_effect = np.where(dates.dayofweek == 5, 1.5, 1)  # 周六增加50%
sales = (sales * weekday_effect).astype(int)df = pd.DataFrame({'date': dates,'sales': sales,'returns': np.random.randint(0, 10, size=len(dates))
})# 设置日期索引
df.set_index('date', inplace=True)# 1. 月度销售分析
monthly_sales = df['sales'].resample('ME').sum()
monthly_avg = df['sales'].resample('ME').mean()# 2. 周分析
df['weekday'] = df.index.day_name()
weekly_sales = df.groupby('weekday')['sales'].mean().reindex(['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'
])# 3. 滚动分析
df['7d_avg'] = df['sales'].rolling(window=7).mean()
df['7d_std'] = df['sales'].rolling(window=7).std()# 4. 节假日分析
cal = USFederalHolidayCalendar()
holidays = cal.holidays(start='2023-01-01', end='2023-06-30')
holiday_sales = df[df.index.isin(holidays)]['sales'].mean()# 5. 时间序列分解
decomposed = seasonal_decompose(df['sales'], model='additive', period=30)print("月度销售总额:\n", monthly_sales)
print("\n周平均销售:\n", weekly_sales)
print("\n节假日平均销售额:", holiday_sales)
月度销售总额:date
2023-01-31    4073
2023-02-28    3558
2023-03-31    3923
2023-04-30    3913
2023-05-31    4063
2023-06-30    4525
Freq: ME, Name: sales, dtype: int64周平均销售:weekday
Monday       119.192308
Tuesday      114.692308
Wednesday    133.961538
Thursday     128.346154
Friday       128.038462
Saturday     178.920000
Sunday       128.923077
Name: sales, dtype: float64节假日平均销售额: 131.4

4:数据分类

5:可视化和SQL操作

http://www.dtcms.com/a/323023.html

相关文章:

  • 深入解析QUIC协议:下一代音视频传输技术的突破与实践
  • 前端如何安全存储 API 密钥 —— 两种实用方案
  • 动手学深度学习(pytorch版):第二章节——预备知识(1)——数据操作
  • pytorch llm 计算flops和参数量
  • 【C++】继承机制全解析
  • Spring-rabbit使用实战七
  • 48伏电气系统—— 铺就电动出行之路的关键技术
  • 大语言模型中的幻觉
  • 24SpringCloud黑马商城微服务整合Seata重启服务报错的解决办法
  • 使用SymPy lambdify处理齐次矩阵的高效向量化计算
  • Poetry与UV——现代Python依赖管理的革新者
  • GitHub 趋势日报 (2025年08月08日)
  • java10学习笔记
  • EPI2ME分析软件测试
  • Java 8 特性
  • PG靶机 - Shiftdel
  • 计算机网络:CIDR地址块划分子网可以使用VLSM吗?
  • 使用 Vuepress + GitHub Pages 搭建项目文档(2)- 使用 GitHub Actions 工作流自动部署
  • [激光原理与应用-206]:光学器件 - SESAM - 基本结构与工作原理
  • “高大上“的SpringCloud?(微服务体系入门)
  • 关于灰度图像相似度的损失函数(笔记)
  • 【Datawhale AI夏令营】基于多模态RAG的企业财报问答系统
  • MySQL弹幕内容字段设计总结
  • Linux Makefile解析
  • 元宇宙技术如何改变社交方式?
  • MyBatis联合查询 - 注解篇
  • QT系统相关
  • gpt-oss 全量技术解读
  • Alibaba Cloud Linux 3 安装 git
  • 【Spring Boot启动流程底层源码详解】