1.pandas介绍和优点
Pandas 是 2008 年由 Wes McKinney 开发的开源 Python 库 。它专门用于数据挖掘和数据分析,具有以下特点:
- 数据结构独特:核心数据结构为 Series(一维)和 DataFrame(二维) 。Series 可看作带标签的一维数组,能存储多种数据类型;DataFrame 类似电子表格或 SQL 表,是带行列标签的二维数据结构,便于处理结构化数据。
- 基于 Numpy:以 Numpy 为基础构建,借助 Numpy 在数值计算方面高性能、高效能的优势,处理大规模数据时运算速度快。
- 数据处理功能强大:能轻松处理数据的读取、清洗、转换、合并、重塑等操作。比如处理缺失值(填充、删除) ,处理重复值,对数据进行分组聚合计算等。
- 文件读取便捷:支持读取多种格式文件,如 CSV、Excel、JSON、SQL 等 ,方便从不同数据源获取数据。
- 可视化支持:基于 Matplotlib 库,能简便地绘制各类图表,如折线图、柱状图、散点图等,利于数据可视化分析。
优点:
增强图表可读性
- Numpy 原始数据展示:
- 效果:单纯的 Numpy 数组只是数值罗列,没有行列标识,难以直观知道每一行代表哪个学生,每一列代表哪门课程,可读性差。
- Pandas 优化后展示:
import pandas as pd
import numpy as np
scores_numpy = np.array([[92, 55, 78, 50, 50],[71, 76, 50, 48, 96],[45, 84, 78, 51, 68],[81, 91, 56, 54, 76],[86, 66, 77, 67, 95],[46, 86, 56, 61, 99],[46, 95, 44, 46, 56],[80, 50, 45, 65, 57],[41, 93, 90, 41, 97],[65, 83, 57, 57, 40]])
scores_df = pd.DataFrame(scores_numpy, columns=['语文', '数学', '英语', '政治', '体育'],index=[f'同学{i}' for i in range(len(scores_numpy))])
print(scores_df)
- 效果:使用 Pandas 的
DataFrame
将 Numpy 数组转换为表格形式,明确指定了列名(课程名称)和行索引(学生标识) ,数据展示清晰明了,一眼就能定位每个学生对应课程的成绩,极大增强了可读性。
便捷的数据处理能力(以处理缺失值为例)
- 原始数据(含缺失值):
- 效果:生成的 DataFrame 中存在
NaN
表示的缺失值,这些缺失值会影响后续数据分析,如计算均值、统计等操作的准确性。 - 处理缺失值 - 删除法:
import pandas as pd
import numpy as np
data = {'col1': [1, 2, np.nan, 4],'col2': [5, np.nan, 7, 8]
}
df = pd.DataFrame(data)
df_dropped = df.dropna() # 默认丢弃包含任何缺失值的行
print(df_dropped)
- 效果:使用
dropna()
函数,直接剔除了含有缺失值的行,使数据集中不再有缺失值干扰,但可能会丢失部分数据信息。 - 处理缺失值 - 填充法:
- 效果:通过
fillna()
函数,用指定的值(这里是 0)填充了缺失值,保证了数据集的完整性,在不丢失数据行的情况下,让数据可以继续用于后续分析。
2.pandas的数据结构
2.1Series知识点
2.1.1. Series 的定义与结构
Series 是 Pandas 中类似于一维数组的数据结构,能保存整数、字符串、浮点数等任何类型数据,由数据和相关索引两部分构成。就像一个有序的键值对集合,索引相当于键,数据相当于值。
2.1.2 Series 的创建
- 通过已有数据创建 - 指定内容,默认索引
import pandas as pd
import numpy as np
# 使用np.arange(10)生成0到9的一维数组,传入pd.Series创建Series对象
s1 = pd.Series(np.arange(10))
print(s1)
这里pd.Series()
函数,当只传入数据(data
参数),未指定索引(index
参数)时 ,会自动创建从 0 开始的整数索引。运行后会得到一个包含 0 到 9,索引从 0 到 9 的 Series 对象,数据类型(dtype
)为int64
。
- 指定索引
import pandas as pd
# 传入数据列表[6.7, 5.6, 3, 10, 2],并指定索引为[1, 2, 3, 4, 5]
s2 = pd.Series([6.7, 5.6, 3, 10, 2], index=[1, 2, 3, 4, 5])
print(s2)
此代码中,通过index
参数明确指定了索引值。创建出的 Series 对象,索引是 [1, 2, 3, 4, 5] ,对应的数据是 [6.7, 5.6, 3, 10, 2] ,数据类型为float64
。
- 通过字典数据创建
import pandas as pd
# 传入字典{'red':100, 'blue':200, 'green':500, 'yellow':1000}创建Series
color_count = pd.Series({'red':100, 'blue':200, 'green':500, 'yellow':1000})
print(color_count)
用字典创建 Series 时,字典的键会自动成为索引,值成为对应的数据。运行后得到的 Series 对象,索引是 ['blue', 'green','red', 'yellow'] ,数据是 [200, 500, 100, 1000] ,数据类型为int64
。
2.1.2 Series 的属性
- index 属性
import pandas as pd
color_count = pd.Series({'red':100, 'blue':200, 'green':500, 'yellow':1000})
# 获取Series对象的索引
print(color_count.index)
index
属性用于获取 Series 对象的索引。运行代码后,会得到一个 Index 对象,包含了 ['blue', 'green','red', 'yellow'] ,数据类型为object
。
- values 属性
import pandas as pd
color_count = pd.Series({'red':100, 'blue':200, 'green':500, 'yellow':1000})
# 获取Series对象的数据
print(color_count.values)
values
属性用于获取 Series 对象中的数据。运行代码后,会得到一个 Numpy 数组,包含 [200, 500, 100, 1000] ,这就是 Series 中存储的数据内容。
这两个属性都是(n*1)类型的,即列向量。可以用对象.shape()查看。
- 使用索引获取数据
import pandas as pd
color_count = pd.Series({'red':100, 'blue':200, 'green':500, 'yellow':1000})
# 使用索引获取数据,这里索引2对应的值是100
print(color_count[2])
可以像访问数组一样,使用索引来获取 Series 中的数据。这里的索引可以是整数索引(按顺序),也可以是自定义的标签索引(如字典创建时的键 )。运行后会输出索引为 2 对应的数据值 100 。
2.2DataFrame知识点
2.2.1 DataFrame 的定义与结构
DataFrame 是 Pandas 中类似二维数组或表格(如 Excel)的对象,兼具行索引(横向,axis=0 )和列索引(纵向,axis=1 ) ,方便对二维数据进行操作和管理。
2.2.2 DataFrame 的创建
- 通过已有数据创建 - 示例一
import pandas as pd
import numpy as np
# 创建一个2行3列,元素为随机数的DataFrame
df1 = pd.DataFrame(np.random.randn(2, 3))
print(df1)
运行结果类似:
0 1 2
0 -0.834694 -0.147477 0.364357
1 -0.703061 -0.171343 -0.346670
这里使用np.random.randn(2, 3)
生成一个 2 行 3 列的随机数数组,传入pd.DataFrame()
创建 DataFrame。由于未指定索引,行索引和列索引默认从 0 开始编号。
- 示例二:创建学生成绩表
import pandas as pd
import numpy as np
# 生成10名同学,5门功课的随机成绩数据(40到100分之间)
score = np.random.randint(40, 100, (10, 5))
# 直接将数组转换为DataFrame
score_df = pd.DataFrame(score)
print(score_df)
运行结果类似:
0 1 2 3 4
0 92 55 78 50 50
1 71 76 50 48 96
2 45 84 78 51 68
3 81 91 56 54 76
4 86 66 77 67 95
5 46 86 56 61 99
6 46 95 44 46 56
7 80 50 45 65 57
8 41 93 90 41 97
9 65 83 57 57 40
此时虽然将数据转换为了 DataFrame,但列索引是 0 - 4,行索引是 0 - 9,可读性不佳。
- 增加行列索引,提升可读性
import pandas as pd
import numpy as np
score = np.random.randint(40, 100, (10, 5))
# 构造行索引序列
subjects = ["语文", "数学", "英语", "政治", "体育"]
# 构造列索引序列
stu = ['同学' + str(i) for i in range(score.shape[0])]
# 添加行索引和列索引创建DataFrame
data = pd.DataFrame(score, columns=subjects, index=stu)
print(data)
运行结果类似:
语文 数学 英语 政治 体育
同学0 92 55 78 50 50
同学1 71 76 50 48 96
同学2 45 84 78 51 68
同学3 81 91 56 54 76
同学4 86 66 77 67 95
同学5 46 86 56 61 99
同学6 46 95 44 46 56
同学7 80 50 45 65 57
同学8 41 93 90 41 97
同学9 65 83 57 57 40
2.2.3DataFrame 的属性(对象.属性)不加括号
- shape 属性
import pandas as pd
import numpy as np
score = np.random.randint(40, 100, (10, 5))
subjects = ["语文", "数学", "英语", "政治", "体育"]
stu = ['同学' + str(i) for i in range(score.shape[0])]
data = pd.DataFrame(score, columns=subjects, index=stu)
print(data.shape)
运行结果为:(10, 5)
,表示 DataFrame 有 10 行 5 列。
- index 属性
import pandas as pd
import numpy as np
score = np.random.randint(40, 100, (10, 5))
subjects = ["语文", "数学", "英语", "政治", "体育"]
stu = ['同学' + str(i) for i in range(score.shape[0])]
data = pd.DataFrame(score, columns=subjects, index=stu)
print(data.index)
运行结果类似:Index(['同学0', '同学1', '同学2', '同学3', '同学4', '同学5', '同学6', '同学7', '同学8', '同学9'], dtype='object')
,展示了 DataFrame 的行索引内容。
- columns 属性
import pandas as pd
import numpy as np
score = np.random.randint(40, 100, (10, 5))
subjects = ["语文", "数学", "英语", "政治", "体育"]
stu = ['同学' + str(i) for i in range(score.shape[0])]
data = pd.DataFrame(score, columns=subjects, index=stu)
print(data.columns)
运行结果类似:Index(['语文', '数学', '英语', '政治', '体育'], dtype='object')
,展示了 DataFrame 的列索引内容。
- values 属性
import pandas as pd
import numpy as np
score = np.random.randint(40, 100, (10, 5))
subjects = ["语文", "数学", "英语", "政治", "体育"]
stu = ['同学' + str(i) for i in range(score.shape[0])]
data = pd.DataFrame(score, columns=subjects, index=stu)
print(data.values)
运行果类似:
array([[92, 55, 78, 50, 50],[71, 76, 50, 48, 96],[45, 84, 78, 51, 68],[81, 91, 56, 54, 76],[86, 66, 77, 67, 95],[46, 86, 56, 61, 99],[46, 95, 44, 46, 56],[80, 50, 45, 65, 57],[41, 93, 90, 41, 97],[65, 83, 57, 57, 40]])
该属性返回 DataFrame 中的数据,以 Numpy 数组形式呈现。
- T 属性(转置)
import pandas as pd
import numpy as np
score = np.random.randint(40, 100, (10, 5))
subjects = ["语文", "数学", "英语", "政治", "体育"]
stu = ['同学' + str(i) for i in range(score.shape[0])]
data = pd.DataFrame(score, columns=subjects, index=stu)
print(data.T)
运行结果类似:
同学0 同学1 同学2 同学3 同学4 同学5 同学6 同学7 同学8 同学9
语文 92 71 45 81 86 46 46 80 41 65
数学 55 76 84 91 66 86 95 50 93 83
英语 78 50 78 56 77 56 44 45 90 57
政治 50 48 51 54 67 61 46 65 41 57
体育 50 96 68 76 95 99 56 57 97 40
T
属性将 DataFrame 的行和列进行转置,即原来的行变为列,原来的列变为行。
- head () 方法
import pandas as pd
import numpy as np
score = np.random.randint(40, 100, (10, 5))
subjects = ["语文", "数学", "英语", "政治", "体育"]
stu = ['同学' + str(i) for i in range(score.shape[0])]
data = pd.DataFrame(score, columns=subjects, index=stu)
print(data.head(5))
运行结果类似:
语文 数学 英语 政治 体育
同学0 92 55 78 50 50
同学1 71 76 50 48 96
同学2 45 84 78 51 68
同学3 81 91 56 54 76
同学4 86 66 77 67 95
head()
方法默认显示 DataFrame 的前 5 行数据,传入参数N
可显示前N
行 。
- tail () 方法
import pandas as pd
import numpy as np
score = np.random.randint(40, 100, (10, 5))
subjects = ["语文", "数学", "英语", "政治", "体育"]
stu = ['同学' + str(i) for i in range(score.shape[0])]
data = pd.DataFrame(score, columns=subjects, index=stu)
print(data.tail(5))
运行结果类似:
语文 数学 英语 政治 体育
同学5 46 86 56 61 99
同学6 46 95 44 46 56
同学7 80 50 45 65 57
同学8 41 93 90 41 97
同学9 65 83 57 57 40
tail()
方法默认显示 DataFrame 的后 5 行数据,传入参数N
可显示后N
行 。
2.2.4修改行列索引值
假设有一个已有的 DataFrame data
(基于之前学生成绩表示例 ),要修改行索引值。使用对象.index=新索引(列表)
import pandas as pd
import numpy as np
# 生成10名同学,5门功课的随机成绩数据(40到100分之间)
score = np.random.randint(40, 100, (10, 5))
subjects = ["语文", "数学", "英语", "政治", "体育"]
stu = ['同学' + str(i) for i in range(score.shape[0])]
data = pd.DataFrame(score, columns=subjects, index=stu)
# 构造新的行索引列表
new_stu = ["学生_" + str(i) for i in range(data.shape[0])]
# 整体修改行索引
data.index = new_stu
print(data)
这里不能像data.index[3] = '学生_3'
这样单独修改某个索引值,因为index
属性是整体赋值的,需要一次性替换整个索引序列。本质是index是一个不可变对象,你修改不可变对象就是重新开辟了一个空间把index指向这个空间,所以这个index-new要重新全部更改。
2.3.2 重设索引
对象.reset_index(drop=)
drop=False
(默认情况)
import pandas as pd
import numpy as np
score = np.random.randint(40, 100, (10, 5))
subjects = ["语文", "数学", "英语", "政治", "体育"]
stu = ['同学' + str(i) for i in range(score.shape[0])]
data = pd.DataFrame(score, columns=subjects, index=stu)
# 重设索引,不删除原来索引
new_data = data.reset_index()
print(new_data)
运行后,会新增一列从 0 开始的整数索引,原来的行索引(如同学0
等 )变成了名为index
的普通列。
drop=True
import pandas as pd
import numpy as np
score = np.random.randint(40, 100, (10, 5))
subjects = ["语文", "数学", "英语", "政治", "体育"]
stu = ['同学' + str(i) for i in range(score.shape[0])]
data = pd.DataFrame(score, columns=subjects, index=stu)
# 重设索引,删除原来索引
new_data = data.reset_index(drop=True)
print(new_data)
此时,原来的行索引被直接删除,仅保留从 0 开始的新整数索引。
2.3.3 以某列值设置为新的索引
对象.set_index(列(可以多个之后讲))
- 设置单索引
import pandas as pd
# 创建示例DataFrame
df = pd.DataFrame({'month': [1, 4, 7, 10],'year': [2012, 2014, 2013, 2014],'sale': [55, 40, 84, 31]})
# 以month列设置为新的索引,默认drop=True,删除原来的month列
new_df = df.set_index('month')
print(new_df)
运行后,month
列的值成为了新的索引,原month
列被删除(因为drop=True
)。
- 设置多索引
import pandas as pd
df = pd.DataFrame({'month': [1, 4, 7, 10],'year': [2012, 2014, 2013, 2014],'sale': [55, 40, 84, 31]})
# 以year和month列设置为新的索引
new_df = df.set_index(['year','month'])
print(new_df)
运行后,DataFrame 变为具有多层索引(MultiIndex)的结构 ,year
和month
共同构成索引,方便从不同层级对数据进行筛选和分析。
3.基本数据操作(注意这里讲解二维结构,但一维也适用,只不过是特殊的二维)
3.1索引查找操作
数据准备
import pandas as pd
# 读取文件
data = pd.read_csv("./data/stock_day.csv")
# 删除一些列,让数据更简单些,再去做后面的操作
data = data.drop(["ma5","ma10","ma20","v_ma5","v_ma10","v_ma20"], axis=1)
这里pd.read_csv()
用于读取 CSV 格式文件,参数为文件路径,将文件数据读取为 DataFrame。data.drop()
用于删除指定列,keys
参数是要删除的列名列表(这里是 ["ma5","ma10","ma20","v_ma5","v_ma10","v_ma20"] ),axis=1
表示按列删除(axis=0
表示按行 )。
3.1.1 直接使用行列索引 (先列后行)
- 代码及结果
# 直接使用行列索引名字的方式 (先列后行)
result = data['open']['2018-02-27']
print(result)
# 输出:23.53
- 总结:这种方式先通过列名获取对应列(返回 Series ),再通过行索引获取对应行数据。但不支持先指定行再指定列(如
data['2018-02-27']['open']
),也不支持类似 Numpy 的切片语法(如data[:1, :2]
) 。
3.1.2 结合 loc 或者 iloc 使用索引,两者都是先行后列,但使用的方法不同
- 使用 loc,loc只能用index和columns名字检索
# 使用loc:只能指定行列索引的名字
result_loc = data.loc['2018-02-27':'2018-02-22', 'open']
print(result_loc)
运行结果(示例 ):
2018-02-27 23.53
2018-02-26 22.80
2018-02-23 22.88
Name: open, dtype: float64
- 总结:
data.loc[]
中只能使用索引名称进行操作,不能使用位置下标 。 - 使用 iloc
- 代码及结果
# 使用iloc可以通过索引的下标去获取
# 获取前3天数据,前5列的结果
result_iloc = data.iloc[:3, :5]
print(result_iloc)
运行结果(示例 ):
open high close low
2018-02-27 23.53 25.88 24.16 23.53
2018-02-26 22.80 23.78 23.53 22.80
2018-02-23 22.88 23.37 22.82 22.71
- 总结:
data.iloc[]
中只能使用位置下标进行操作,不能使用索引名称 。
3.1.3 使用 ix 组合索引(有些版本已弃用,但是很好用,它可以混合使用)
- 代码及结果
# 使用ix进行下标和名称组合做索引
# 因已弃用,实际运行会有警告提示,这里仅展示代码形式
result_ix = data.ix[:4, ['open', 'close', 'high', 'low']]
print(result_ix)
运行结果(示例 )
- 推荐替代方案及总结
- 使用 loc,都转化为索引名
result_loc_alternative = data.loc[data.index[:4], ['open', 'close', 'high', 'low']]
print(result_loc_alternative)
- 使用 iloc,都转化为下标,可以使用get_indexer函数来得到对应的下标
col_indices = data.columns.get_indexer(['open', 'close', 'high', 'low'])
result_iloc_alternative = data.iloc[:4, col_indices]
print(result_iloc_alternative)
ix
在 Pandas 0.20.0 后已弃用,推荐使用loc
(基于索引名称 )和iloc
(基于索引位置 )替代。loc
中第一个参数通过data.index[:4]
获取前 4 个行索引名称,第二个参数是列名列表;iloc
中第一个参数是行索引位置范围,第二个参数通过data.columns.get_indexer()
获取指定列名的位置索引 。
这里为大家展示一下一种基本用法,就是无论怎么样索引,那个位置可以是一个列表,作用就是拆开这个列表,分别去检索比如对象.ix(1,[2,3])就可以检索到第二行第三列和第4列的数据。
3.2赋值操作
很简单,通过索引之后直接赋值即可。
3.3排序操作
3.3.1 DataFrame 排序(一维二维数据都是对象.sort_index/values())
sort_values
函数- 按单个键排序
import pandas as pd
# 读取股票数据
data = pd.read_csv("./data/stock_day.csv")
# 按照开盘价大小进行升序排序并查看前几行
sorted_data_single = data.sort_values(by="open", ascending=True).head()
print(sorted_data_single)
这里by="open"
指定以open
(开盘价)这一列作为排序参考的键 ,ascending=True
表示升序排列。运行后会得到按开盘价升序排列的前几行股票数据。
- 按多个键排序
import pandas as pd
data = pd.read_csv("./data/stock_day.csv")
# 按照open和high列进行排序
sorted_data_multiple = data.sort_values(by=['open', 'high'])
print(sorted_data_multiple)
by=['open', 'high']
指定以open
列和high
列作为排序参考的键,默认升序排列。先按open
列排序,若open
列值相同,再按high
列排序。
sort_index
函数
import pandas as pd
data = pd.read_csv("./data/stock_day.csv")
# 对索引进行排序(假设索引是日期,从小到大排序)
sorted_index_data = data.sort_index()
print(sorted_index_data)
sort_index
函数用于对 DataFrame 的索引进行排序,默认升序。这里假设索引是日期,运行后会将索引(日期)从小到大重新排列数据。
3.3.2 Series 排序
sort_values
函数
import pandas as pd
data = pd.read_csv("./data/stock_day.csv")
# 对p_change列数据(Series)进行升序排序并查看前几行
sorted_series_values = data['p_change'].sort_values(ascending=True).head()
print(sorted_series_values)
ascending=True
指定升序,对p_change
列(Series)的数据进行升序排列,然后通过head()
查看前几行。
sort_index
函数
import pandas as pd
data = pd.read_csv("./data/stock_day.csv")
# 对p_change列(Series)的索引进行排序并查看前几行
sorted_series_index = data['p_change'].sort_index().head()
print(sorted_series_index)
sort_index
函数对p_change
列(Series)的索引进行排序,默认升序,然后通过head()
查看前几行排序后的结果。
4.DataFrame运算
4.1. 算术运算
add(other)
函数
import pandas as pd
data = pd.read_csv("./data/stock_day.csv")
# 对open列的数据都加上1
result_add = data['open'].add(1)
print(result_add.head())
add(other)
函数用于对 Series 或 DataFrame 进行加法运算,这里other
为 1 ,将data['open']
中的每个元素都加上 1 。类似的还有sub()
(减法)、mul()
(乘法)、div()
(除法)等函数。
4.2. 逻辑运算
- 逻辑运算符号
- 单条件筛选
import pandas as pd
data = pd.read_csv("./data/stock_day.csv")
# 筛选open列大于23的数据
result_single_condition = data[data["open"] > 23].head()
print(result_single_condition)
data["open"] > 23
返回一个布尔型 Series,True 表示对应行的open
值大于 23 ,然后将其作为索引条件筛选出满足条件的行。
- 多条件筛选
import pandas as pd
data = pd.read_csv("./data/stock_day.csv")
# 筛选open列大于23且小于24的数据
result_multiple_condition = data[(data["open"] > 23) & (data["open"] < 24)].head()
print(result_multiple_condition)
多个条件组合时,每个条件需用括号括起来,&
表示逻辑与,筛选出同时满足两个条件的行。
- 逻辑运算函数
query(expr)
函数
import pandas as pd
data = pd.read_csv("./data/stock_day.csv")
# 使用query筛选open列大于23且小于24的数据
result_query = data.query("open<24 & open>23").head()
print(result_query)
query(expr)
中expr
是查询字符串,以更简洁的语法实现条件筛选,效果与上述多条件筛选类似。
isin(values)
函数
import pandas as pd
data = pd.read_csv("./data/stock_day.csv")
# 筛选open列值为23.53或23.85的数据
result_isin = data[data["open"].isin([23.53, 23.85])]
print(result_isin)
isin(values)
用于判断列中的值是否在指定的values
列表中(注意不是区间),返回布尔型 Series,进而筛选出符合条件的行。
4.3. 统计运算
describe()
函数
import pandas as pd
data = pd.read_csv("./data/stock_day.csv")
# 对数据进行综合统计分析
result_describe = data.describe()
print(result_describe)
describe()
函数自动计算数值列的计数(count)、均值(mean)、标准差(std)、最小值(min)、25% 分位数(25% )、50% 分位数(中位数,50% )、75% 分位数(75% )、最大值(max)等统计量。
- 统计函数
- 按列计算统计量
import pandas as pd
data = pd.read_csv("./data/stock_day.csv")
# 按列计算最大值
result_max = data.max()
print(result_max)
默认axis=0
,按列计算,返回每列的最大值。
- 按行计算统计量
import pandas as pd
data = pd.read_csv("./data/stock_day.csv")
# 按行计算最大值
result_max_row = data.max(axis=1)
print(result_max_row.head())
指定axis=1
,按行计算,返回每行的最大值。其他统计函数如min()
、mean()
、median()
等用法类似。
- 累计统计函数(有很多用的时候自己查)
cumsum()
函数示例
import pandas as pd
data = pd.read_csv("./data/stock_day.csv")
# 计算p_change列的累计和
result_cumsum = data['p_change'].cumsum()
print(result_cumsum.head())
cumsum()
计算前 1/2/3/.../n 个数的和,其他累计统计函数cummax()
(计算前 n 个数的最大值 )、cummin()
(计算前 n 个数的最小值 )、cumprod()
(计算前 n 个数的积 )用法类似。
绘图展示(cumsum
结果可视化)
import pandas as pd
import matplotlib.pyplot as plt
data = pd.read_csv("./data/stock_day.csv")
# 计算p_change列的累计和
stock_rise = data['p_change']
cumulative_sum = stock_rise.cumsum()
# 绘制累计和图形
cumulative_sum.plot()
# 显示图形
plt.show()
通过matplotlib
库的plot()
函数绘制累计和的折线图,plt.show()
展示图形,直观呈现数据累计变化趋势
4.4自定义运算apply
函数
apply(func, axis=0)
函数用于对 DataFrame 的行或列应用自定义函数进行运算。
- 参数
func
:是一个自定义函数,可以是普通函数定义,也可以是 lambda 匿名函数,用于指定具体的运算逻辑。axis
:指定运算的方向,axis=0
(默认值)表示按列运算,即对每一列应用函数;axis=1
表示按行运算,即对每一行应用函数。
- 代码示例
import pandas as pd
# 假设已读取股票数据
data = pd.read_csv("./data/stock_day.csv")
# 定义一个lambda匿名函数,计算每列的最大值减去最小值
result = data[['open', 'close']].apply(lambda x: x.max() - x.min(), axis=0)
print(result)
这里使用 lambda 表达式定义了一个函数,功能是计算传入数据(列数据 )的最大值与最小值之差。axis=0
指定按列进行运算,所以最终得到open
列和close
列各自的最大值与最小值的差值。
如果要按行运算,示例如下:
import pandas as pd
data = pd.read_csv("./data/stock_day.csv")
# 定义按行计算open和close列差值的函数
def row_diff(row):return row['open'] - row['close']
result_row = data[['open', 'close']].apply(row_diff, axis=1)
print(result_row.head())
这里定义了普通函数row_diff
,接收一行数据,计算该行中open
列与close
列的差值。axis=1
指定按行运算,最终得到每行中open
与close
的差值。
5.pandas画图(很简单,因为很简单所以绘制一些复杂图还得使用matplotlib)
数据.plot(kind="")即可,kind里面放类型就行
6.文件的读取和存储(其实函数都一样都是pd.read_格式()和pd.to_格式)
6.1. CSV 文件操作
6.1.1 read_csv
函数
- 函数语法及参数
pandas.read_csv(filepath_or_buffer, sep=',', usecols=None, header='infer', ...)
filepath_or_buffer
:必填参数,用于指定要读取的 CSV 文件路径,既可以是本地文件路径,也可以是类似 URL 的远程文件路径。例如"./data/stock_day.csv"
,表示当前目录下data
文件夹中的stock_day.csv
文件。sep
:可选参数,指定文件中数据的分隔符,默认为逗号','
。在实际应用中,如果 CSV 文件是用制表符'\t'
分隔数据,就需要设置sep='\t'
。usecols
:可选参数,用于指定读取文件时需要选取的列。可以是列名组成的列表,如['open', 'close']
,表示只读取文件中的open
列和close
列数据。header
:可选参数,用于指定文件中哪一行作为列名。默认值为'infer'
,即自动推断文件第一行是否为列名。如果文件没有列名,可以设置header=None
,并在读取后手动指定列名;如果列名在第二行,可设置header=1
。
- 代码示例
import pandas as pd
# 读取文件,并且指定只获取'open', 'close'指标
data = pd.read_csv("./data/stock_day.csv", usecols=['open', 'close'])
print(data.head())
此代码从"./data/stock_day.csv"
文件中读取数据,仅选取open
列和close
列,然后展示前几行数据。
6.1.2 to_csv
函数
- 函数语法及参数
DataFrame.to_csv(path_or_buf=None, sep=',', columns=None, header=True, index=True, mode='w', encoding=None, ...)
path_or_buf
:必填参数,指定保存 CSV 文件的路径或文件对象。如"./data/test.csv"
,表示将 DataFrame 数据保存到当前目录下data
文件夹中的test.csv
文件。sep
:可选参数,指定保存文件时数据的分隔符,默认为逗号','
,用法与read_csv
中的sep
类似。columns
:可选参数,用于指定要保存到文件中的列。如['open']
,表示只将 DataFrame 中的open
列保存到 CSV 文件。header
:可选参数,布尔值或字符串列表,默认为True
,表示将 DataFrame 的列名写入文件作为表头。若设置为False
,则不写入列名;若传入字符串列表,如['col1', 'col2']
,则使用传入的字符串作为列名写入文件。index
:可选参数,布尔值,默认为True
,表示将 DataFrame 的索引写入文件。若设置为False
,则不写入索引。mode
:可选参数,指定文件写入模式,'w'
表示重写(覆盖原文件),'a'
表示追加(在原文件末尾添加数据)。
- 代码示例
import pandas as pd
# 假设data是已有的DataFrame
data = pd.DataFrame({'open': [23.53, 22.80, 22.88], 'close': [24.16, 23.53, 22.82]})
# 选取10行数据保存,便于观察数据
data[:10].to_csv("./data/test.csv", columns=['open'], index=False)
# 读取,查看结果
read_data = pd.read_csv("./data/test.csv")
print(read_data)
此代码先从data
中选取前 10 行数据,将其中的open
列保存到"./data/test.csv"
文件中,并且不保存索引。然后再读取该文件并展示内容。
6.2. HDF5 文件操作
6.2.1 read_hdf
与to_hdf
函数
pandas.read_hdf
函数- 函数语法及参数
pandas.read_hdf(path_or_buf, key=None, **kwargs)
path_or_buf
:必填参数,用于指定 HDF5 文件的路径,可以是本地文件路径,如"./data/day_close.h5"
,表示当前目录下data
文件夹中的day_close.h5
文件。key
:必填参数,指定要从 HDF5 文件中读取的数据的主键。HDF5 文件可存储多个数据集,通过键来区分和读取特定数据集。如果数据只有一列,无需指定**kwargs
:可选参数,用于传递其他关键字参数,可用于进一步配置读取行为,如数据格式转换等。
- 代码示例
- 函数语法及参数
import pandas as pd
# 从HDF5文件中读取数据
day_eps_ttm = pd.read_hdf("./data/day_close.h5", key="day_eps_ttm")
print(day_eps_ttm.head())
此代码从"./data/day_close.h5"
文件中,读取键为day_eps_ttm
的数据,并展示前几行内容。
DataFrame.to_hdf
函数- 函数语法及参数
DataFrame.to_hdf(path_or_buf, key, **kwargs)
path_or_buf
:必填参数,指定要保存 HDF5 文件的路径,如"./data/test.h5"
,表示将数据保存到当前目录下data
文件夹中的test.h5
文件。key
:必填参数,为要保存到 HDF5 文件中的 DataFrame 数据指定一个键,后续读取时通过该键获取数据。**kwargs
:可选参数,可用于设置保存时的一些参数,如压缩方式等。HDF5 默认支持blosc
压缩方式,能提高磁盘利用率,节省空间。
- 代码示例
- 函数语法及参数
import pandas as pd
# 假设day_eps_ttm是已有的DataFrame
day_eps_ttm = pd.DataFrame({'col1': [1, 2, 3], 'col2': [4, 5, 6]})
# 将DataFrame保存到HDF5文件中
day_eps_ttm.to_hdf("./data/test.h5", key="day_eps_ttm")
# 再次读取文件中的数据
new_eps = pd.read_hdf("./data/test.h5", key="day_eps_ttm")
print(new_eps)
此代码先将day_eps_ttm
这个 DataFrame 保存到"./data/test.h5"
文件中,键为day_eps_ttm
,然后再从该文件中读取对应键的数据并展示。
6.2.2 案例及优点
- 案例:在读取 HDF5 文件时,若出现
ModuleNotFoundError: No module named 'tables'
错误,是因为缺少tables
模块,需使用pip install tables
命令安装该模块,才能正常读取 HDF5 文件。 - 优点:HDF5 文件存储具有优势,支持
blosc
压缩, - 可提高磁盘利用率、节省空间,
- 跨平台的,便于迁移到 Hadoop 等平台,所以优先选择使用 HDF5 文件存储。
6.3. JSON 文件操作
6.3.1 read_json
函数
- 函数语法及参数
pandas.read_json(path_or_buf=None, orient=None, typ='frame', lines=False)
path_or_buf
:可选参数,用于指定 JSON 文件路径或者包含 JSON 数据的缓冲区。如果是读取本地文件,可传入文件路径,如"./data/Sarcasm_Headlines_Dataset.json"
。orient
:可选参数,用于指定 JSON 字符串的预期格式,常见取值及含义如下:'split'
:字典形式,如{index -> [index], columns -> [columns], data -> [values]}
,将索引、列名和数据分开存储。'records'
:列表形式,如[{column -> value}, ... ,{column -> value}]
,以columns: values
的形式输出。'index'
:字典形式,如{index -> {column -> value}}
,以index: {columns: values}...
的形式输出。'columns'
:字典形式,如{column -> {index -> value}}
,这是默认格式,以columns:{index:values}
的形式输出。'values'
:直接输出值数组。- 怎么样存的怎么样读就行
typ
:可选参数,默认值为'frame'
,指定转换后的对象类型,可选择'series'
或'dataframe'
。lines
:可选参数,布尔值,默认False
。当设置为True
时,按照每行读取 JSON 对象。
- 代码示例
import pandas as pd
# 读取JSON文件,指定格式为'records',按行读取
json_read = pd.read_json("./data/Sarcasm_Headlines_Dataset.json", orient="records", lines=True)
print(json_read.head())
此代码从"./data/Sarcasm_Headlines_Dataset.json"
文件中读取 JSON 数据,将其转换为 DataFrame 格式,指定orient="records"
和lines=True
,然后展示前几行数据。
6.3.2 to_json
函数
- 函数语法及参数
DataFrame.to_json(path_or_buf=None, orient=None, lines=False)
path_or_buf
:可选参数,指定保存 JSON 文件的路径或者文件缓冲区。若要保存到本地文件,可传入文件路径,如"./data/test.json"
。orient
:可选参数,取值与read_json
中的orient
类似,用于指定存储的 JSON 形式。lines
:可选参数,布尔值,默认False
。当设置为True
时,每个对象存储为一行。
- 代码示例
import pandas as pd
# 假设json_read是已读取的DataFrame
json_read = pd.DataFrame({'article_link': ['https://example1.com'], 'headline': ['Headline 1'], 'is_sarcastic': [0]})
# 保存为JSON文件,指定格式为'records'
json_read.to_json("./data/test.json", orient='records')
# 修改lines参数为True后保存
json_read.to_json("./data/test.json", orient='records', lines=True)
此代码先将json_read
这个 DataFrame 以'records'
格式保存为 JSON 文件,然后再以'records'
格式且lines=True
的方式重新保存,改变了文件存储的格式结构。
6.4 Excel 文件操作
6.4.1 to_excel
函数
- 函数语法及参数
to_excel(excel_writer, sheet_name='Sheet1', na_rep='', index=True)
excel_writer
:必填参数,用于指定保存 Excel 文件的路径。例如'./data/itcast.xlsx'
,表示将 DataFrame 数据保存到当前目录下data
文件夹中的itcast.xlsx
文件。sheet_name
:可选参数,用于指定工作表的名称,默认为'Sheet1'
。可以传入字符串,如'python基础班'
,将数据写入指定名称的工作表。na_rep
:可选参数,用于指定缺失数据的表示方式,默认为空字符串''
。若数据中存在缺失值,会按此参数设置的方式显示。index
:可选参数,布尔值,默认为True
,表示是否将 DataFrame 的索引写入 Excel 文件。若设置为False
,则不写入索引。
- 代码示例
import pandas as pd
# 创建一个2行2列的DataFrame对象
df1 = pd.DataFrame({'col1': ['传', '智'], 'col2': ['播', '客']})
# 将DataFrame对象写入Excel文件
df1.to_excel('./data/itcast.xlsx', 'python基础班')
print('写入完毕')
此代码先创建了一个简单的 DataFrame,然后使用to_excel
函数将其保存到'./data/itcast.xlsx'
文件的'python基础班'
工作表中。
6.4.2 read_excel
函数
- 函数语法及参数
read_excel(io, sheet_name=0)
io
:必填参数,用于指定 Excel 文件的路径,可以是字符串形式的文件路径,如'./data/itcast.xlsx'
。sheet_name
:可选参数,用于指定要读取的工作表。可以传入字符串(工作表名称)或整数(工作表索引,从 0 开始 )。默认值为0
,表示读取第一个工作表
6.5SQL的读取与执行
read_sql
函数
- 函数语法及参数
pandas.read_sql(sql, con, index_col=None, params=None, columns=None)
sql
:必填参数,表示要执行的 SQL 语句。可以是简单的表名(读取整张表 ),如'goods'
,也可以是复杂的查询语句,如'select * from goods where price > 5000'
。con
:必填参数,用于接收数据库连接信息。通常通过create_engine
函数创建,例如engine = create_engine('mysql+pymysql://root:mysql@127.0.0.1/jing_dong')
,这里mysql
是数据库类型,pymysql
是数据库驱动名称,root:mysql
是用户名和密码,127.0.0.1
是机器地址,jing_dong
是数据库名。index_col
:可选参数,默认为None
。如果传入一个列表,则表示将这些列设置为层次化索引。params
:可选参数,用于传递给执行方法的参数列表,格式如params={'mame': 'vale'}
。columns
:可选参数,接收列表,表示要读取数据的列名,默认为None
,即读取所有列。
- 代码示例
import pandas as pd
import pymysql
from sqlalchemy import create_engine
# 创建数据库连接
engine = create_engine('mysql+pymysql://root:mysql@127.0.0.1/jing_dong')
# 读取整张goods表
df1 = pd.read_sql('goods', engine)
# 执行SQL查询语句,读取price大于5000的记录
sql ='select * from goods where price > 5000'
df2 = pd.read_sql(sql, engine)
print(df1.head())
print(df2.head())
此代码先创建了数据库连接,然后分别演示了读取整张表和执行 SQL 查询语句读取部分数据的操作。
to_sql
函数
- 函数语法及参数
to_sql(name, con, if_exists='fail', index=True)
name
:必填参数,用于指定要写入数据库的数据表名称。con
:必填参数,同read_sql
中的con
,用于接收数据库连接信息。if_exists
:可选参数,默认值为'fail'
。有'fail'
(如果表已存在,操作失败)、'replace'
(如果表已存在,先删除表再创建新表写入数据)、'append'
(如果表已存在,在表尾追加数据)三种取值。index
:可选参数,布尔值,默认为True
,表示是否将 Series 或 DataFrame 的索引写入数据库表。
- 代码示例
import pandas as pd
import pymysql
from sqlalchemy import create_engine
# 创建数据库连接
engine = create_engine('mysql+pymysql://root:mysql@127.0.0.1/jing_dong')
# 假设df是已有的DataFrame
df = pd.DataFrame({'col1': [1, 2], 'col2': [3, 4]})
# 将DataFrame写入数据库表test_table
df.to_sql('test_table', engine, if_exists='replace', index=False)
此代码将df
这个 DataFrame 写入名为test_table
的数据库表中,若表已存在则替换,并且不写入索引。