【Python工具】Pandas数据分析处理库(一)
【Python工具】Pandas数据分析处理库
1、Pandas

潘哒斯~
Pandas 是一个开源的数据分析和数据处理库,它是基于 Python 编程语言的。Pandas 提供了易于使用的数据结构和数据分析工具,特别适用于处理结构化数据,如表格型数据(类似于Excel表格)。Pandas 是数据科学和分析领域中常用的工具之一,它使得用户能够轻松地从各种数据源中导入数据,并对数据进行高效的操作和分析。
- 用得最多的pandas对象是Series,一个一维的标签化数组对象,另一个是DataFrame,它是一个面向列的二维表结构。

1.1、Pandas优点
Numpy已经能够帮助我们处理数据,能够结合matplotlib解决部分数据展示等问题,那么pandas学习的目的在什么地方呢?
- 增强图表可读性
- 便捷的数据处理能力
- 读取文件方便
- 封装了Matplotlib、Numpy的画图和计算

# 安装
conda install pandas
2、Pandas数据结构
Pandas中一共有三种数据结构,分别为:
- Series:一维数据结构
- DataFrame:二维的表格型的数据结构
- MultiIndex:三维的数据结构(了解)
2.1、Series
Series是一个类似于一维数组的数据结构,它能够保存任何类型的数据,比如整数、字符串、浮点数等,**主要由一组数据和与之相关的索引两部分构成。**其实类似于Java的Map结构

2.1.1、Series的创建
# 导入pandas
import pandas as pd
pd.Series(data=None, index=None, dtype=None)
参数:
- data:传入的数据,可以是ndarray、list等
- index:索引,必须是唯一的,且与数据的长度相等。如果没有传入索引参数,则默认会自动创建一个从0-N的整数索引。
- dtype:数据的类型
import pandas as pd
s = pd.Series([4, 7, -5, 3])
print(s)
# 0 4
# 1 7
# 2 -5
# 3 3
# dtype: int64

Series的字符串表现形式为:索引在左边,值在右边。由于我们没有为数据指定索引,于是会自动创建一个0到N-1(N为数据的长度)的整数型索引
通过已有数据创建:
- 指定内容,默认索引
# np.arange(10) 生成随机0-10,步长默认为1的数组
pd.Series(np.arange(10))

- 指定索引
pd.Series([6.7,5.6,3,10,2], index=[1,2,3,4,5])

- 通过字典数据创建
color_count = pd.Series({'red':100, 'blue':200, 'green': 500, 'yellow':1000})
color_count

2.1.2、Series的属性
| 属性 | 说明 |
|---|---|
| index | Series的索引对象 |
| values | Series的值 |
| ndim | Series的维度 |
| shape | Series的形状 |
| size | Series的元素个数 |
| dtype或dtypes | Series的元素类型 |
| name | Series的名称 |
| loc[] | 显式索引,按标签索引或切片 |
| iloc[] | 隐式索引,按位置索引或切片 |
| at[] | 使用标签访问单个元素 |
| iat[] | 使用位置访问单个元素 |
为了更方便地操作Series对象中的索引和数据,Series中提供了两个属性index和values
- 索引index
import numpy as np
# 导入pandas
import pandas as pd
color_count = pd.Series({'red':100, 'blue':200, 'green': 500, 'yellow':1000})
# 查看全部索引
color_count.index
# 查看全部值
color_count.values

也可以使用索引来获取数据:

import pandas as pd
arrs = pd.Series([11,22,33,44,55],name="atguigu",index=["a","b","c","d","e"])
# index Series的索引对象
print(arrs.index) # Index(['a', 'b', 'c', 'd', 'e'], dtype='object')
"""
a
b
c
d
e
"""
for i in arrs.index:
print(i)
# values Series的值
print(arrs.values) # [11 22 33 44 55]
# ndim Series的维度
print(arrs.ndim) # 1维
# shape Series的形状
print(arrs.shape) # (5,) 5行1列
# size Series的元素个数
print(arrs.size) # 5
# dtype或dtypes Series的元素类型
print(arrs.dtype)
print(arrs.dtypes)
# name Series的名称
print(arrs.name) # atguigu

import pandas as pd
arrs = pd.Series([11,22,33,44,55],name="atguigu",index=["a","b","c","d","e"])
# loc[] 显式索引,按标签索引
# 查找索引标签为 "c" 的元素
print(arrs.loc["c"])
# 选取从标签 "c" 到 "d" 的所有元素。[]闭区间
print(arrs.loc["c":"d"])
# iloc[] 隐式索引,按位置索引
# 查找第 0 个位置的元素(即第一个元素)
print(arrs.iloc[0])
# 选取从位置 0 到 3 的元素 [)区间
print(arrs.iloc[0:3])
# 优化版本(使用这个)
# at[] 使用标签访问单个元素
# 查找索引标签为 "a" 的元素
print(arrs.at["a"])
# iat[] 使用位置访问单个元素
# 查找第 3 个位置的元素
print(arrs.iat[3])

2.1.3、Series的常用方法
| 方法 | 说明 |
|---|---|
| head() | 查看前n行数据,默认5行 |
| tail() | 查看后n行数据,默认5行 |
| isin() | 元素是否包含在参数集合中 |
| isna() | 元素是否为缺失值(通常为 NaN 或 None) |
| sum() | 求和,会忽略 Series 中的缺失值 |
| mean() | 平均值 |
| min() | 最小值 |
| max() | 最大值 |
| var() | 方差 |
| std() | 标准差 |
| median() | 中位数 |
| mode() | 众数(出现频率最高的值),如果有多个值出现的频率相同且都是最高频率,这些值都会被包含在返回的 Series 中 |
| quantile(q,interpolation) | 指定位置的分位数q的取值范围是 0 到 1 之间的浮点数或浮点数列表,如quantile(0.5)表示计算中位数(即第 50 百分位数);interpolation:指定在计算分位数时,如果分位数位置不在数据点上,采用的插值方法。默认值是线性插值 ‘linear’,还有其他可选值如 ‘lower’、‘higher’、‘midpoint’、‘nearest’ 等 |
| describe() | 常见统计信息 |
| value_count() | 每个元素的个数 |
| count() | 非缺失值元素的个数,如果要包含缺失值,用len() |
| drop_duplicates() | 去重 |
| unique() | 去重后的数组 |
| nunique() | 去重后元素个数 |
| sample() | 随机采样 |
| sort_index() | 按索引排序 |
| sort_values() | 按值排序 |
| replace() | 用指定值代替原有值 |
| to_frame() | 将Series转换为DataFrame |
| equals() | 判断两个Series是否相同 |
| keys() | 返回Series的索引对象 |
| corr() | 计算与另一个Series的相关系数 默认使用皮尔逊相关系数(Pearson correlation coefficient)来计算相关性。要求参与比较的数组元素类型都是数值型。当相关系数为 1 时,表示两个变量完全正相关,即一个变量增加,另一个变量也随之增加。当相关系数为 -1 时,表示两个变量完全负相关,即一个变量增加,另一个变量随之减少。当相关系数为 0 时,表示两个变量之间不存在线性相关性。例如,分析某地区的气温和冰淇淋销量之间的关系 |
| cov() | 计算与另一个Series的协方差 |
| hist() | 绘制直方图,用于展示数据的分布情况。它将数据划分为若干个区间(也称为 “bins”),并统计每个区间内数据的频数。需要安装matplotlib包 |
| items() | 获取索引名以及值 |
import pandas as pd
import numpy as np
arrs = pd.Series([11,22,np.nan,None,44,22],index=['a','b','c','d','e','f'])
# head() 查看前n行数据,默认5行
print(arrs.head())
# tail() 查看后n行数据,默认5行
print(arrs.tail(3))
# isin() 判断数组中的每一个元素是否包含在参数集合中
print(arrs.isin([11]))
# isna() 元素是否为缺失值
print(arrs.isna())
# sum() 求和,会忽略 Series 中的缺失值
print(arrs.sum())
# mean() 平均值
print(arrs.mean())
# min() 最小值
print(arrs.min())
# max() 最大值
print(arrs.max())
# var() 方差
print(arrs.var())
# std() 标准差
print(arrs.std())
# print(arrs.var())
# median() 中位数
print(arrs.median())
# mode() 众数
print(arrs.mode())
# quantile() 指定位置的分位数,如quantile(0.5)
print(arrs.quantile(0.25, interpolation="midpoint"))
# describe() 常见统计信息
print(arrs.describe())
# value_counts() 每个元素的个数
print(arrs.value_counts())
# count() 非缺失值元素的个数
print(arrs.count())
print(len(arrs))
print(len(arrs))
# drop_duplicates() 去重 这里可以看出,底层None也作为NaN处理
print(arrs.drop_duplicates())
# unique() 去重后的数组
print(arrs.unique())
# nunique() 去重后元素个数
print(arrs.nunique())
# sample() 随机采样
print(arrs.sample())
# sort_index() 按索引排序
print(arrs.sort_index())
# sort_values() 按值排序
print(arrs.sort_values())
# replace() 用指定值代替原有值
print(arrs.replace(22,"haha"))
# to_frame() 将Series转换为DataFrame
print(arrs.to_frame())
# equals() 判断两个Series是否相同
arr1 = pd.Series([1,2,3])
arr2 = pd.Series([1,2,3])
print(arr1.equals(arr2))
# keys() 返回Series的索引对象
print(arrs.index)
print(arrs.keys())
# corr() 计算与另一个Series的相关系数
arr3 = pd.Series([3,2,1])
arr4 = pd.Series([6,7,8])
arr5 = pd.Series([1, -1, 1, -1])
arr6 = pd.Series([1, 1, -1, -1])
print(arr1.corr(arr2))
print(arr1.corr(arr3))
print(arr1.corr(arr4))
print(arr5.corr(arr6))
# cov() 计算与另一个Series的协方差
print(arr1.corr(arr3))
# hist() 绘制直方图
arr7 = pd.Series([3,2,1,1,1,2,2])
# 绘制直方图
arr7.hist(bins=3)
# items() 获取索引名以及值
for i,v in arr7.items():
print(i,v)
2.1.4、Series的布尔索引
可以使用布尔索引从Series中筛选满足某些条件的值。
import pandas as pd
s = pd.Series({"a": -1.2, "b": 3.5, "c": 6.8, "d": 2.9})
bools = s > s.mean() # 将大于平均值的元素标记为 True
print(bools) # 打印上一步生成的布尔序列
# a False
# b True
# c True
# d False
# dtype: bool
# Pandas 会检查 bools 中的每一个值,只保留 s 中对应位置为 True 的元素,而丢弃对应位置为 False 的元素。
print(s[bools]) #
# b 3.5
# c 6.8
# dtype: float64

2.1.5、Series的运算
- Series与标量运算:标量会与每个元素进行计算
import pandas as pd
s = pd.Series({"a": -1.2, "b": 3.5, "c": 6.8, "d": 2.9})
print(s * 10)
# a -12.0
# b 35.0
# c 68.0
# d 29.0
# dtype: float64
- Series与Series运算:会根据标签索引进行对位计算,索引没有匹配上的会用NaN填充
import pandas as pd
s1 = pd.Series([1, 1, 1, 1])
s2 = pd.Series([2, 2, 2, 2], index=[1, 2, 3, 4])
print(s1 + s2)
# 0 NaN
# 1 3.0
# 2 3.0
# 3 3.0
# 4 NaN
# dtype: float64

2.2、DataFrame
DataFrame是一个类似于二维数组或表格(如excel)的对象,既有行索引,又有列索引
- 行索引,表明不同行,横向索引,叫index,0轴,axis=0
- 列索引,表名不同列,纵向索引,叫columns,1轴,axis=1
- 可以把DataFrame看作由Series对象组成的字典,其中key是列名,值是Series
2.2.1、DataFrame的创建
# 导入pandas
import pandas as pd
pd.DataFrame(data=None, index=None, columns=None)
- 参数:
- index:行标签。如果没有传入索引参数,则默认会自动创建一个从0-N的整数索引。
- columns:列标签。如果没有传入索引参数,则默认会自动创建一个从0-N的整数索引。
# np.random.randn(2,3)随机生成2行3列的值
pd.DataFrame(np.random.randn(2,3))

DataFrame的创建有两种方式:
- 直接通过字典创建DataFrame
df = pd.DataFrame({"id": [101, 102, 103], "name": ["张三", "李四", "王五"], "age": [20, 30, 40]})
print(df)
# id name age
# 0 101 张三 20
# 1 102 李四 30
# 2 103 王五 40

- 通过字典创建时指定列的顺序和行索引
df = pd.DataFrame(
data={"age": [20, 30, 40], "name": ["张三", "李四", "王五"]}, columns=["name", "age"], index=[101, 102, 103]
)
print(df)
# name age
# 101 张三 20
# 102 李四 30
# 103 王五 40

举例:创建学生成绩表
# 生成10名同学,5门功课的数据
score = np.random.randint(40, 100, (10, 5))
# 使用Pandas中的数据结构
score_df = pd.DataFrame(score)

但是这样可读性比较差,我们加上行列索引,显示结果更佳:
# 构造行索引序列
subjects = ["语文", "数学", "英语", "政治", "体育"]
# 构造列索引序列
stu = ['同学' + str(i) for i in range(score_df.shape[0])]
# 添加行索引
data = pd.DataFrame(score, columns=subjects, index=stu)

2.2.2、DataFrame的属性
| 属性 | 说明 |
|---|---|
| index | DataFrame的行索引 |
| columns | DataFrame的列标签 |
| values | DataFrame的值 |
| ndim | DataFrame的维度 |
| shape | DataFrame的形状 |
| size | DataFrame的元素个数 |
| dtypes | DataFrame的元素类型 |
| T | 行列转置 |
| loc[] | 显式索引,按行列标签索引或切片 |
| iloc[] | 隐式索引,按行列位置索引或切片 |
| at[] | 使用行列标签访问单个元素 |
| iat[] | 使用行列位置访问单个元素 |
import pandas as pd
df = pd.DataFrame(data={"id": [101, 102, 103], "name": ["张三", "李四", "王五"], "age": [20, 30, 40]},index=["aa", "bb", "cc"])
# index DataFrame的行索引
# Index(['aa', 'bb', 'cc'], dtype='object')
print(df.index)
# columns DataFrame的列标签
# Index(['id', 'name', 'age'], dtype='object')
print(df.columns)
# values DataFrame的值
"""
[[101 '张三' 20]
[102 '李四' 30]
[103 '王五' 40]]
"""
print(df.values)
# ndim DataFrame的维度
print(df.ndim) # 2
# shape DataFrame的形状
print(df.shape) # (3, 3)
# size DataFrame的元素个数
print(df.size)
# dtypes DataFrame的元素类型
"""
id int64
name object
age int64
"""
print(df.dtypes)
# T 行列转置
print(df.T)
# loc[] 显式索引,按行列标签索引或切片
print(df.loc["aa":"cc"])
print(df.loc[:,["id","name"]])
# iloc[] 隐式索引,按行列位置索引或切片
print(df.iloc[0:1])
print(df.iloc[0:3,2])
print("----------")
# at[] 使用行列标签访问单个元素
print(df.at["aa","name"])
# iat[] 使用行列位置访问单个元素
print(df.iat[0,1])

- shape:查看是几行几列

- index:DataFrame的行索引列表

- columns:DataFrame的列索引列表

- values:直接获取其中array的值

- T:转置

- head(5):显示前5行内容.如果不补充参数,默认5行。填入参数N则显示前N行

- tail(5):显示后5行内容。如果不补充参数,默认5行。填入参数N则显示后N行
2.2.3、DataFrame的常用方法
| 方法 | 说明 |
|---|---|
| head() | 查看前n行数据,默认5行 |
| tail() | 查看后n行数据,默认5行 |
| isin() | 元素是否包含在参数集合中 |
| isna() | 元素是否为缺失值 |
| sum() | 求和 |
| mean() | 平均值 |
| min() | 最小值 |
| max() | 最大值 |
| var() | 方差 |
| std() | 标准差 |
| median() | 中位数 |
| mode() | 众数 |
| quantile() | 指定位置的分位数,如quantile(0.5) |
| describe() | 常见统计信息 |
| info() | 基本信息 |
| value_counts() | 每个元素的个数 |
| count() | 非空元素的个数 |
| drop_duplicates() | 去重 |
| sample() | 随机采样 |
| replace() | 用指定值代替原有值 |
| equals() | 判断两个DataFrame是否相同 |
| cummax() | 累计最大值 |
| cummin() | 累计最小值 |
| cumsum() | 累计和 |
| cumprod() | 累计积 |
| diff() | 一阶差分,对序列中的元素进行差分运算,也就是用当前元素减去前一个元素得到差值,默认情况下,它会计算一阶差分,即相邻元素之间的差值。参数:periods:整数,默认为 1。表示要向前或向后移动的周期数,用于计算差值。正数表示向前移动,负数表示向后移动。axis:指定计算的轴方向。0 或 ‘index’ 表示按列计算,1 或 ‘columns’ 表示按行计算,默认值为 0。 |
| sort_index() | 按行索引排序 |
| sort_values() | 按某列的值排序,可传入列表来按多列排序,并通过ascending参数设置升序或降序 |
| nlargest() | 返回某列最大的n条数据 |
| nsmallest() | 返回某列最小的n条数据 |
在Pandas的 DataFrame 方法里,axis 是一个非常重要的参数,它用于指定操作的方向。axis 参数可以取两个主要的值,即 0 或 ‘index’,以及 1 或 ‘columns’ ,其含义如下:
- axis=0 或 axis=‘index’:表示操作沿着行的方向进行,也就是对每一列的数据进行处理。
- axis=1 或 axis=‘columns’:表示操作沿着列的方向进行,也就是对每一行的数据进行处理。
import pandas as pd
df = pd.DataFrame(data={"id": [101, 102, 103,104,105,106,101], "name": ["张三", "李四", "王五","赵六","冯七","周八","张三"], "age": [10, 20, 30, 40, None, 60,10]},index=["aa", "bb", "cc", "dd", "ee", "ff","aa"])
# head() 查看前n行数据,默认5行
print(df.head())
# tail() 查看后n行数据,默认5行
print(df.tail())
# isin() 元素是否包含在参数集合中
print(df.isin([103,106]))
# isna() 元素是否为缺失值
print(df.isna())
# sum() 求和
print(df["age"].sum())
# mean() 平均值
print(df["age"].mean())
# min() 最小值
print(df["age"].min())
# max() 最大值
print(df["age"].max())
# var() 方差
print(df["age"].var())
# std() 标准差
print(df["age"].std())
# median() 中位数
print(df["age"].median())
# mode() 众数
print(df["age"].mode())
# quantile() 指定位置的分位数,如quantile(0.5)
print(df["age"].quantile(0.5))
# describe() 常见统计信息
print(df.describe())
# info() 基本信息
print(df.info())
# value_counts() 每个元素的个数
print(df.value_counts())
# count() 非空元素的个数
print(df.count())
# drop_duplicates() 去重
print(df.duplicated(subset="age"))
# sample() 随机采样
print(df.sample())
# replace() 用指定值代替原有值
print("----------------")
print(df.replace(20,"haha"))
# equals() 判断两个DataFrame是否相同
df1 = pd.DataFrame(data={"id": [101, 102, 103], "name": ["张三", "李四", "王五"], "age": [10, 20, 30]})
df2 = pd.DataFrame(data={"id": [101, 102, 103], "name": ["张三", "李四", "王五"], "age": [10, 20, 30]})
print(df1.equals(df2))
# cummax() 累计最大值
df3 = pd.DataFrame({'A': [2, 5, 3, 7, 4],'B': [1, 6, 2, 8, 3]})
# 按列 等价于axis=0 默认
print(df3.cummax(axis="index"))
# 按行 等价于axis=1
print(df3.cummax(axis="columns"))
# cummin() 累计最小值
print(df3.cummin())
# cumsum() 累计和
print(df3.cumsum())
# cumprod() 累计积
print(df3.cumprod())
# diff() 一阶差分
print(df3.diff())
# sort_index() 按行索引排序
print(df.sort_index())
# sort_values() 按某列的值排序,可传入列表来按多列排序,并通过ascending参数设置升序或降序
print(df.sort_values(by="age"))
# nlargest() 返回某列最大的n条数据
print(df.nlargest(n=2,columns="age"))
# nsmallest() 返回某列最小的n条数据
print(df.nsmallest(n=1,columns="age"))

2.2.4、DataFrame的布尔索引
import pandas as pd
df = pd.DataFrame(
data={"age": [20, 30, 40, 10], "name": ["张三", "李四", "王五", "赵六"]},
columns=["name", "age"],
index=[101, 104, 103, 102],
)
"""
101 False
104 True
103 True
102 False
Name: age, dtype: bool
"""
print(df["age"] > 25)
"""
name age
104 李四 30
103 王五 40
"""
print(df[df["age"] > 25])

2.2.3、DataFrame的更改操作
创建行索引:创建DataFrame时如果不指定行索引,pandas会自动添加从0开始的索引。
import pandas as pd
df = pd.DataFrame({"age": [20, 30, 40, 10], "name": ["张三", "李四", "王五", "赵六"], "id": [101, 102, 103, 104]})
print(df)
# age name id
# 0 20 张三 101
# 1 30 李四 102
# 2 40 王五 103
# 3 10 赵六 104

- 通过
set_index()设置行索引

- 通过reset_index()重置行索引
df.reset_index(inplace=True) # 重置索引
print(df)
# id age name
# 0 101 20 张三
# 1 102 30 李四
# 2 103 40 王五
# 3 104 10 赵六
修改行索引名和列名:
- 通过rename()修改行索引名和列名
import pandas as pd
df = pd.DataFrame({"age": [20, 30, 40, 10], "name": ["张三", "李四", "王五", "赵六"], "id": [101, 102, 103, 104]})
df.set_index("id", inplace=True) # 设置id为索引
print(df)
# age name
# id
# 101 20 张三
# 102 30 李四
# 103 40 王五
# 104 10 赵六
df.rename(
# 把行索引从数字(101、102...)改为中文 一、二、三、四
index={101: "一", 102: "二", 103: "三", 104: "四"},
# 把列名 age 改为 "年龄",name 改为 "姓名"
columns={"age": "年龄", "name": "姓名"},
# 同样表示直接修改原 DataFrame
inplace=True)
print(df)
# 年龄 姓名
# id
# 一 20 张三
# 二 30 李四
# 三 40 王五
# 四 10 赵六

- 将index和columns重新赋值
df.index = ["Ⅰ", "Ⅱ", "Ⅲ", "Ⅳ"]
df.columns = ["年齡", "名稱"]
print(df)
# 年齡 名稱
# Ⅰ 20 张三
# Ⅱ 30 李四
# Ⅲ 40 王五
# Ⅳ 10 赵六
- 添加列:通过 df[“列名”] 添加列
import pandas as pd
df = pd.DataFrame({"age": [20, 30, 40, 10], "name": ["张三", "李四", "王五", "赵六"], "id": [101, 102, 103, 104]})
df.set_index("id", inplace=True) # 设置id为索引
# age name
# id
# 101 20 张三
# 102 30 李四
# 103 40 王五
# 104 10 赵六
df["phone"] = ["13333333333", "14444444444", "15555555555", "16666666666"]
print(df)

- 删除列:通过 df.drop(“列名”, axis=1) 删除,也可是删除行 axis=0
df.drop("phone", axis=1, inplace=True) # 删除phone,按列删除,inplace=True表示直接在原对象上修改
- 通过 del df[“列名”] 删除
del df["phone"]
插入列:通过 insert(loc, column, value) 插入。该方法没有inplace参数,直接在原数据上修改。
# loc 参数需要一个整数,代表列的索引位置。loc=0 表示将新列插入到 DataFrame 的最前面,成为第一列。
# 新列的名称是 "phone"
# 将 "age" 列中的每一个值与它对应的行索引值进行逐元素相乘,就是新列 "phone" 中要填充的数据
df.insert(loc=0, column="phone", value=df["age"] * df.index)
2.2.4、DataFrame的数据导入与导出
- 导出数据
| 方法 | 说明 |
|---|---|
| to_csv() | 将数据保存为csv格式文件,数据之间以逗号分隔,可通过sep参数设置使用其他分隔符,可通过index参数设置是否保存行标签,可通过header参数设置是否保存列标签。 |
| to_pickle() | 如要保存的对象是计算的中间结果,或者保存的对象以后会在Python中复用,可把对象保存为.pickle文件。如果保存成pickle文件,只能在python中使用。文件的扩展名可以是.p、.pkl、.pickle。 |
| to_excel() | 保存为Excel文件,需安装openpyxl包。 |
| to_clipboard() | 保存到剪切板。 |
| to_dict() | 保存为字典。 |
| to_hdf() | 保存为HDF格式,需安装tables包。 |
| to_html() | 保存为HTML格式,需安装lxml、html5lib、beautifulsoup4包。 |
| to_json() | 保存为JSON格式。 |
| to_feather() | feather是一种文件格式,用于存储二进制对象。feather对象也可以加载到R语言中使用。feather格式的主要优点是在Python和R语言之间的读写速度要比csv文件快。feather数据格式通常只用中间数据格式,用于Python和R之间传递数据,一般不用做保存最终数据。需安装pyarrow包。 |
| to_sql() | 保存到数据库。 |
import os
import pandas as pd
os.makedirs("data", exist_ok=True)
df = pd.DataFrame({"age": [20, 30, 40, 10], "name": ["张三", "李四", "王五", "赵六"], "id": [101, 102, 103, 104]})
df.set_index("id", inplace=True)
df.to_csv("data/df.csv")
df.to_csv("data/df.tsv", sep="\t") # 设置分隔符为 \t
df.to_csv("data/df_noindex.csv", index=False) # index=False 不保存行索引
df.to_pickle("data/df.pkl")
df.to_excel("data/df.xlsx")
df.to_clipboard()
df_dict = df.to_dict()
df.to_hdf("data/df.h5", key="df")
df.to_html("data/df.html")
df.to_json("data/df.json")
df.to_feather("data/df.feather")
- 导入数据
| 方法 | 说明 |
|---|---|
| read_csv() | 加载csv格式的数据。可通过sep参数指定分隔符,可通过index_col参数指定行索引。 |
| read_pickle() | 加载pickle格式的数据。 |
| read_excel() | 加载Excel格式的数据。 |
| read_clipboard() | 加载剪切板中的数据。 |
| read_hdf() | 加载HDF格式的数据。 |
| read_html() | 加载HTML格式的数据。 |
| read_json() | 加载JSON格式的数据。 |
| read_feather() | 加载feather格式的数据。 |
| read_sql() | 加载数据库中的数据。 |
df_csv = pd.read_csv("data/df.csv", index_col="id") # 指定行索引
df_tsv = pd.read_csv("data/df.tsv", sep="\t") # 指定分隔符
df_pkl = pd.read_pickle("data/df.pkl")
df_excel = pd.read_excel("data/df.xlsx", index_col="id")
df_clipboard = pd.read_clipboard(index_col="id")
df_from_dict = pd.DataFrame(df_dict)
df_hdf = pd.read_hdf("data/df.h5", key="df")
df_html = pd.read_html("data/df.html", index_col=0)[0]
df_json = pd.read_json("data/df.json")
df_feather = pd.read_feather("data/df.feather")
print(df_csv)
print(df_tsv)
print(df_pkl)
print(df_excel)
print(df_clipboard)
print(df_from_dict)
print(df_hdf)
print(df_html)
print(df_json)
print(df_feather)
2.3、MultiIndex
MultiIndex是三维的数据结构;多级索引(也称层次化索引)是pandas的重要功能,可以在Series、DataFrame对象上拥有2个以及2个以上的索引。
2.3.1、创建MultiIndex
MultiIndex.from_arrays():传入一个数组列表
arrays = [[1, 1, 2, 2], ['red', 'blue', 'red', 'blue']]
pd.MultiIndex.from_arrays(arrays, names=('number', 'color'))

忙忒Index
2.3.2、MultiIndex的属性
- index属性
- names:levels的名称
- levels:每个level的元组值
待补充
2.4、排序
排序有两种形式,一种对于索引进行排序,一种对于内容进行排序
2.4.1、DataFrame排序
使用df.sort_values(by=, ascending=)单个键或者多个键进行排序
- by:指定排序参考的键
- ascending:默认升序
- ascending=False:降序
- ascending=True:升序
# 按照开盘价大小进行排序 , 使用ascending指定按照大小排序
data.sort_values(by="open", ascending=True).head()
# 按照多个键进行排序
data.sort_values(by=['open', 'high'])

- 使用df.sort_index给索引进行排序
这个股票的日期索引原来是从大到小,现在重新排序,从小到大
# 对索引进行排序
data.sort_index()

2.4.2、Series排序
- 使用series.sort_values(ascending=True)进行排序
series排序时,只有一列,不需要参数
data['p_change'].sort_values(ascending=True).head()

- 使用series.sort_index()对索引进行排序
3、Pandas日期数据处理
3.1、to_datetime()进行日期格式转换
参数说明:
| 参数名 | 说明 |
|---|---|
| arg | 要转换为日期时间的对象 |
| errors | ignore,raise,coerce, 默认为ignore,表示无效的解析将会返回原值 |
| dayfirst | 指定日期解析顺序。如果为True,则以日期开头解析日期,例如:“10/11/12”解析为2012-11-10。默认false |
| yearfirst | 如果为True,则以日期开头解析,例如:“10/11/12”解析为2010-11-12。如果dayfirst和yearfirst都为True,则yearfirst在前面。默认false。当日期字符串格式不明确时,指定年份是否在最前面。当日期字符串是 ‘2010/1/4’ 这种形式,由于年份是 4 位数字,pandas 能很清晰地识别出这是年份,所以即使 yearfirst 为 False,也不会影响其正确解析 |
| utc | 返回utc,即协调世界时间 |
| format | 格式化显示时间的格式,字符串,默认值为None |
| exact | 要求格式完全匹配 |
| unit | 参数的单位表示时间的单位 |
| infer_datetime_format | 如果为True且未给出格式,则尝试基于第一个非nan元素推断datetime字符串的格式,如果可以推断,则切换到更快的解析方法。在某些情况下,这可以将解析速度提高5-10倍。 |
| origin | 默认值为unix,定义参考日期1970-01-01 |
| cache | 使用唯一的已转换日期缓存来应用日期时间转换。在解析重复日期字符串时产生显著的加速。 |
- 将字符串字段转换为日期类型
import pandas as pd
df = pd.DataFrame({"gmv":[100,200,300,400],"trade_date":["2025-01-06","2023-10-31","2023-12-31","2023-01-05"]})
# 原本 trade_date 列中的日期只是普通的文本(字符串),计算机无法理解其时间先后顺序。转换后,ymd 列变成了真正的时间格式,可以进行时间计算、排序或提取年份/月份等操作
df["ymd"] = pd.to_datetime(df["trade_date"])
print(df)

3.2、获取年月日星期
- 获取年月日
import pandas as pd
df = pd.DataFrame({"gmv":[100,200,300,400],"trade_date":["2025-01-06","2023-10-31","2023-12-31","2023-01-05"]})
# 原本 trade_date 列中的日期只是普通的文本(字符串),计算机无法理解其时间先后顺序。转换后,ymd 列变成了真正的时间格式,可以进行时间计算、排序或提取年份/月份等操作
df["ymd"] = pd.to_datetime(df["trade_date"])
# 1. 提取年份:从 ymd 列中取出年份(如 2025),存入新列 'yy'
df['yy'] = df['ymd'].dt.year
# 2. 提取月份:从 ymd 列中取出月份(如 1),存入新列 'mm'
df['mm'] = df['ymd'].dt.month
# 3. 提取日期:从 ymd 列中取出日期(如 6),存入新列 'dd'
df['dd'] = df['ymd'].dt.day
print(df)

- 获取星期
df['week']=df['ymd'].dt.day_name()
print(df)
- 获取日期所在季度
df['quarter']=df['ymd'].dt.quarter
print(df)
- 判断日期是否月底年底
df['mend']=df['ymd'].dt.is_month_end
df['yend']=df['ymd'].dt.is_year_end
print(df)
3.3、to_period()获取统计周期
freq:这是 to_period() 方法最重要的参数,用于指定要转换的时间周期频率
常见的取值如下:
- D:按天周期,例如 2024-01-01 会转换为 2024-01-01 这个天的周期
- W:按周周期,通常以周日作为一周的结束,比如日期落在某一周内,就会转换为该周的周期表示。
- M:按月周期,像 2024-05-15 会转换为 2024-05
- Q:按季度周期,一年分为四个季度,日期会转换到对应的季度周期,例如 2024Q2
- A或Y:按年周期,如 2024-07-20 会转换为 2024
import pandas as pd
df = pd.DataFrame({"gmv":[100,200,300,400],"trade_date":["2025-01-06","2023-10-31","2023-12-31","2023-01-05"]})
# 原本 trade_date 列中的日期只是普通的文本(字符串),计算机无法理解其时间先后顺序。转换后,ymd 列变成了真正的时间格式,可以进行时间计算、排序或提取年份/月份等操作
df["ymd"] = pd.to_datetime(df["trade_date"])
df["ystat"] = df["ymd"].dt.to_period("Y")
df["mstat"] = df["ymd"].dt.to_period("M")
df["qstat"] = df["ymd"].dt.to_period("Q")
df["wstat"] = df["ymd"].dt.to_period("W")
print(df)

4、Pandas画图
使用pandas.DataFrame的plot方法绘制图像会按照数据的每一列绘制一条曲线,默认按照列columns的名称在适当的位置展示图例,比matplotlib绘制节省时间,且DataFrame格式的数据更规范,方便向量化及计算。
4.1、折线图Line
- 普通用法
ts = pd.Series(np.random.randn(1000), index=pd.date_range("1/1/2000", periods=1000))
ts = ts.cumsum().plot()
np.random.randn(1000): 这部分是利用NumPy库生成一个包含1000个元素的数组,这些元素是从标准正态分布(均值为0,标准差为1的正态分布)中随机抽取的。pd.Series(...): 这部分是将上述生成的随机数组转换为一个Pandas的Series对象。Pandas的Series是一种一维数组结构,它可以存储任何数据类型(整数、字符串、浮点数、Python对象等),每个元素都有一个标签(索引)。index=pd.date_range("1/1/2000", periods=1000): 这里为Series对象指定了一个索引。pd.date_range函数生成了一个日期范围,从"1/1/2000"(即2000年1月1日)开始,总共生成1000个日期。这意味着每个随机生成的数值都会与一个特定的日期相关联。

- 展示多列数据
df = pd.DataFrame(np.random.randn(1000, 4), index=pd.date_range("1/1/2000", periods=1000), columns=list("ABCD"))
df = df.cumsum().plot()
np.random.randn(1000, 4): 这部分生成了一个1000行4列的数组,数组中的每个元素都是从标准正态分布中随机抽取的。这意味着你将有1000个观测值,每个观测值都有4个特征或变量。pd.DataFrame(...): 这部分将上述生成的随机数组转换为一个Pandas的DataFrame对象。DataFrame是Pandas中用于存储和操作结构化数据的主要数据结构。index=pd.date_range("1/1/2000", periods=1000): 与之前的示例类似,这里为DataFrame指定了一个索引。pd.date_range函数生成了一个从"1/1/2000"(即2000年1月1日)开始的日期范围,总共1000个日期。这些日期将作为DataFrame的行索引。columns=list("ABCD"): 这里为DataFrame指定了列标签。list("ABCD")创建了一个包含四个字符串(“A”, “B”, “C”, “D”)的列表,这些字符串将作为DataFrame的列名。


若要让时间刻度良好展示,可以:
plot(x_compat=True)

4.2、条形图bar
df = pd.DataFrame(np.random.rand(10, 4), columns=["a", "b", "c", "d"])
df.plot.bar()

若要生成堆积条形图,可加参数
bar(stacked=True)

若要生成水平条形图:
df.plot.barh()

剩余图形请参考更好的文章:pandas plot绘图详解:一文教会你各种绘图
5、Pandas数据组合函数
5.1、Concat连接
沿着一条轴将多个对象堆叠到一起,可通过axis参数设置沿哪一条轴连接。
- Series与Series连接
import pandas as pd
s1 = pd.Series(["A", "B"], index=[1, 2])
s2 = pd.Series(["D", "E"], index=[4, 5])
s3 = pd.Series(["G", "H"], index=[7, 8])
s4 = pd.concat([s1, s2, s3]) # 按行连接
print(s4)
"""
1 A
2 B
4 D
5 E
7 G
8 H
dtype: object
"""

s5 = pd.concat([s1, s2, s3], axis=1) # 按列连接 ,缺失值会用NaN填充
print(s5)
"""
0 1 2
1 A NaN NaN
2 B NaN NaN
4 NaN D NaN
5 NaN E NaN
7 NaN NaN G
8 NaN NaN H
"""

- DataFrame与Series连接
df1 = pd.DataFrame(data={"a": [1, 2], "b": [4, 5]}, index=[1, 2])
s1 = pd.Series(data=[7, 10], index=[1, 2], name="a")
pd.concat([df1, s1]) # 按行连接
# a b
# 1 1 4.0
# 2 2 5.0
# 1 7 NaN
# 2 10 NaN
pd.concat([df1, s1], axis=1) # 按列连接
# a b a
# 1 1 4 7
# 2 2 5 10

- DataFrame与DataFrame连接
df1 = pd.DataFrame(data={"a": [1, 2], "b": [4, 5]}, index=[1, 2])
df2 = pd.DataFrame(data={"a": [7, 8], "b": [10, 11]}, index=[1, 2])
pd.concat([df1, df2]) # 按行连接
# a b
# 1 1 4
# 2 2 5
# 1 7 10
# 2 8 11
pd.concat([df1, df2], axis=1) # 按列连接
# a b a b
# 1 1 4 7 10
# 2 2 5 8 11

- 可通过ignore_index=True来重置索引
df1 = pd.DataFrame(data={"a": [1, 2], "b": [4, 5]}, index=[1, 2])
df2 = pd.DataFrame(data={"a": [7, 8], "b": [10, 11]}, index=[1, 2])
pd.concat([df1, df2], ignore_index=True) # 重置索引
# a b
# 0 1 4
# 1 2 5
# 2 7 10
# 3 8 11
- join:默认的合并方式是对其他轴进行并集合并(join=outer),可以用join=inner实现其他轴上的交集合并。
df1 = pd.DataFrame(data={"a": [1, 2], "b": [4, 5]}, index=[1, 2])
df2 = pd.DataFrame(data={"b": [7, 8], "c": [10, 11]}, index=[2, 3])
pd.concat([df1, df2])
# a b c
# 1 1.0 4 NaN
# 2 2.0 5 NaN
# 2 NaN 7 10.0
# 3 NaN 8 11.0
pd.concat([df1, df2], join="inner")
# b
# 1 4
# 2 5
# 2 7
# 3 8
5.2、merge
merge合并:通过一个或多个列将行连接
merge()实现了三种数据连接的类型:一对一、多对一和多对多:
(1)、一对一连接
df1 = pd.DataFrame(
{"employee": ["Bob", "Jake", "Lisa", "Sue"], "group": ["Accounting", "Engineering", "Engineering", "HR"]}
)
df2 = pd.DataFrame({"employee": ["Lisa", "Bob", "Jake", "Sue"], "hire_date": [2004, 2008, 2012, 2014]})
print(df1)
# employee group
# 0 Bob Accounting
# 1 Jake Engineering
# 2 Lisa Engineering
# 3 Sue HR
print(df2)
# employee hire_date
# 0 Lisa 2004
# 1 Bob 2008
# 2 Jake 2012
# 3 Sue 2014
# 通过相同的字段名employee进行关联的
df3 = pd.merge(df1, df2)
print(df3)
# employee group hire_date
# 0 Bob Accounting 2008
# 1 Jake Engineering 2012
# 2 Lisa Engineering 2004
# 3 Sue HR 2014
(2)、多对一连接:在需要连接的两个列中,有一列的值有重复。通过多对一连接获得的结果将会保留重复值。
df1 = pd.DataFrame(
{"employee": ["Bob", "Jake", "Lisa", "Sue"], "group": ["Accounting", "Engineering", "Engineering", "HR"]}
)
df2 = pd.DataFrame({"group": ["Accounting", "Engineering", "HR"], "supervisor": ["Carly", "Guido", "Steve"]})
print(df1)
# employee group
# 0 Bob Accounting
# 1 Jake Engineering
# 2 Lisa Engineering
# 3 Sue HR
print(df2)
# group supervisor
# 0 Accounting Carly
# 1 Engineering Guido
# 2 HR Steve
# 通过相同的字段名group进行关联的
df3 = pd.merge(df1, df2)
print(df3)
# employee group supervisor
# 0 Bob Accounting Carly
# 1 Jake Engineering Guido
# 2 Lisa Engineering Guido
# 3 Sue HR Steve
在supervisor列中有些值会因为输入数据的对应关系而有所重复。
(3)、多对多连接:如果左右两个输入的共同列都包含重复值,那么合并的结果就是一种多对多连接
df1 = pd.DataFrame(
{"employee": ["Bob", "Jake", "Lisa", "Sue"], "group": ["Accounting", "Engineering", "Engineering", "HR"]}
)
df2 = pd.DataFrame(
{
"group": ["Accounting", "Accounting", "Engineering", "Engineering", "HR", "HR"],
"skills": ["math", "spreadsheets", "coding", "linux", "spreadsheets", "organization"],
}
)
print(df1)
# employee group
# 0 Bob Accounting
# 1 Jake Engineering
# 2 Lisa Engineering
# 3 Sue HR
print(df2)
# group skills
# 0 Accounting math
# 1 Accounting spreadsheets
# 2 Engineering coding
# 3 Engineering linux
# 4 HR spreadsheets
# 5 HR organization
df3 = pd.merge(df1, df2)
print(df3)
# employee group skills
# 0 Bob Accounting math
# 1 Bob Accounting spreadsheets
# 2 Jake Engineering coding
# 3 Jake Engineering linux
# 4 Lisa Engineering coding
# 5 Lisa Engineering linux
# 6 Sue HR spreadsheets
# 7 Sue HR organization
多对多连接产生的是行的笛卡尔积。由于左边有2个Engineering,右边有2个Engineering,所以最终结果有4个Engineering。
(4)、设置合并的键与索引:merge()会将两个输入的一个或多个共同列作为键进行合并。但由于两个输入要合并的列通常都不是同名的,因此merge()提供了一些参数处理这个问题。
- 通过on指定使用某个列连接,只能在有共同列名的时候使用
df1 = pd.DataFrame(
{"employee": ["Bob", "Jake", "Lisa", "Sue"], "group": ["Accounting", "Engineering", "Engineering", "HR"]}
)
df2 = pd.DataFrame({"employee": ["Lisa", "Bob", "Jake", "Sue"], "hire_date": [2004, 2008, 2012, 2014]})
print(df1)
# employee group
# 0 Bob Accounting
# 1 Jake Engineering
# 2 Lisa Engineering
# 3 Sue HR
print(df2)
# employee hire_date
# 0 Lisa 2004
# 1 Bob 2008
# 2 Jake 2012
# 3 Sue 2014
# 指定使用 employee 列进行连接
df3 = pd.merge(df1, df2, on="employee")
print(df3)
# employee group hire_date
# 0 Bob Accounting 2008
# 1 Jake Engineering 2012
# 2 Lisa Engineering 2004
# 3 Sue HR 2014
- 两对象列名不同,通过left_on和right_on分别指定列名
df1 = pd.DataFrame(
{"employee": ["Bob", "Jake", "Lisa", "Sue"], "group": ["Accounting", "Engineering", "Engineering", "HR"]}
)
df2 = pd.DataFrame({"name": ["Bob", "Jake", "Lisa", "Sue"], "salary": [70000, 80000, 120000, 90000]})
print(df1)
# employee group
# 0 Bob Accounting
# 1 Jake Engineering
# 2 Lisa Engineering
# 3 Sue HR
print(df2)
# name salary
# 0 Bob 70000
# 1 Jake 80000
# 2 Lisa 120000
# 3 Sue 90000
# 将 df1 和 df2 按照 df1 的 "employee" 列与 df2 的 "name" 列进行匹配,把匹配成功的行合并成一个新的 DataFrame df3
df3 = pd.merge(df1, df2, left_on="employee", right_on="name")
print(df3)
# employee group name salary
# 0 Bob Accounting Bob 70000
# 1 Jake Engineering Jake 80000
# 2 Lisa Engineering Lisa 120000
# 3 Sue HR Sue 90000
- 通过left_index和right_index设置合并的索引:通过设置merge()中的left_index、right_index参数将索引设置为键来实现合并。
df1 = pd.DataFrame(
{"employee": ["Bob", "Jake", "Lisa", "Sue"], "group": ["Accounting", "Engineering", "Engineering", "HR"]}
)
df2 = pd.DataFrame({"employee": ["Lisa", "Bob", "Jake", "Sue"], "hire_date": [2004, 2008, 2012, 2014]})
df1.set_index("employee", inplace=True)
df2.set_index("employee", inplace=True)
print(df1)
# group
# employee
# Bob Accounting
# Jake Engineering
# Lisa Engineering
# Sue HR
print(df2)
# hire_date
# employee
# Lisa 2004
# Bob 2008
# Jake 2012
# Sue 2014
# 设置索引后,如果不指定关联列会报错,建议通过以下方式指定,on="employee"也可#以实现,但是不同的解释器可能效果不一样,因为设置索引后,employee就不算是列了
df3 = pd.merge(df1, df2, left_index=True, right_index=True)
# group hire_date
# employee
# Bob Accounting 2008
# Jake Engineering 2012
# Lisa Engineering 2004
# Sue HR 2014
DataFrame实现了join()方法,可以按照索引进行数据合并。但要求没有重叠的列,或通过lsuffix、rsuffix指定重叠列的后缀。
import pandas as pd
df1 = pd.DataFrame({
'key': ['A', 'B', 'C'],
'value1': [1, 2, 3]
})
df2 = pd.DataFrame({
'key': ['B', 'C', 'D'],
'value2': [4, 5, 6]
})
# 合并两个 DataFrame,并处理列名冲突
df1.join(df2,lsuffix='_left',rsuffix='_right')
(5)、设置数据连接的集合操作规则:当一个值出现在一列,却没有出现在另一列时,就需要考虑集合操作规则了。
df1 = pd.DataFrame({"name": ["Peter", "Paul", "Mary"], "food": ["fish", "beans", "bread"]}, columns=["name", "food"])
df2 = pd.DataFrame({"name": ["Mary", "Joseph"], "drink": ["wine", "beer"]}, columns=["name", "drink"])
print(df1)
# name food
# 0 Peter fish
# 1 Paul beans
# 2 Mary bread
print(df2)
# name drink
# 0 Mary wine
# 1 Joseph beer
print(pd.merge(df1, df2))
# name food drink
# 0 Mary bread wine
6、Pandas的缺失值处理函数
pandas使用浮点值NaN(Not a Number)表示缺失数据,使用NA(Not Available)表示缺失值。可以通过isnull()、isna()或notnull()、notna()方法判断某个值是否为缺失值。
- na和nan都用于表示缺失值,但nan更强调是数值计算中的特殊值,而na更强调数据的可用性或存在性。
import pandas as pd
import numpy as np
s = pd.Series([np.nan, None, pd.NA])
print(s)
"""
0 NaN
1 None
2 <NA>
dtype: object
"""
print(s.isnull())
"""
0 True
1 True
2 True
dtype: bool
"""
6.1、剔除缺失值
- Series剔除缺失值
s = pd.Series([1, pd.NA, None])
print(s)
# 0 1
# 1 <NA>
# 2 None
# dtype: object
print(s.dropna())
# 0 1
# dtype: object
- DataFrame剔除缺失值:无法从DataFrame中单独剔除一个值,只能剔除缺失值所在的整行或整列。默认情况下,dropna()会剔除任何包含缺失值的整行数据。
df = pd.DataFrame([[1, pd.NA, 2], [2, 3, 5], [pd.NA, 4, 6]])
print(df)
# 0 1 2
# 0 1 <NA> 2
# 1 2 3 5
# 2 <NA> 4 6
print(df.dropna())
# 0 1 2
# 1 2 3 5
可以设置按不同的坐标轴剔除缺失值,比如axis=1(或 axis=‘columns’)会剔除任何包含缺失值的整列数据。
df = pd.DataFrame([[1, pd.NA, 2], [2, 3, 5], [pd.NA, 4, 6]])
print(df)
# 0 1 2
# 0 1 <NA> 2
# 1 2 3 5
# 2 <NA> 4 6
print(df.dropna(axis=1))
# 2
# 0 2
# 1 5
# 2 6
有时只需要剔除全部是缺失值的行或列,或者绝大多数是缺失值的行或列。这些需求可以通过设置how或thresh参数来满足,它们可以设置剔除行或列缺失值的数量阈值。
df = pd.DataFrame([[1, pd.NA, 2], [pd.NA, pd.NA, 5], [pd.NA, pd.NA, pd.NA]])
print(df)
# 0 1 2
# 0 1 <NA> 2
# 1 <NA> <NA> 5
# 2 <NA> <NA> <NA>
print(df.dropna(how="all")) # 如果所有值都是缺失值,则删除这一行
# 0 1 2
# 0 1 <NA> 2
# 1 <NA> <NA> 5
print(df.dropna(thresh=2)) # 如果至少有2个值不是缺失值,则保留这一行
# 0 1 2
# 0 1 <NA> 2
可以通过设置subset参数来设置某一列有缺失值则进行剔除。
df = pd.DataFrame([[1, pd.NA, 2], [pd.NA, pd.NA, 5], [pd.NA, pd.NA, pd.NA]])
print(df)
# 0 1 2
# 0 1 <NA> 2
# 1 <NA> <NA> 5
# 2 <NA> <NA> <NA>
print(df.dropna(subset=[0])) # 如果0列有缺失值,则删除这一行
# 0 1 2
# 0 1 <NA> 2
6.2、填充缺失值
- 用固定值填充所有缺失值
import pandas as pd
import numpy as np
df = pd.DataFrame({
'A': [1, 2, np.nan, 4],
'B': [5, np.nan, 7, 8]
})
# 用 0 填充所有 NaN
df_filled = df.fillna(0)
print(df_filled)

- 为不同列设置不同的填充值
import pandas as pd
import numpy as np
df = pd.DataFrame({
'A': [1, 2, np.nan, 4],
'B': [5, np.nan, 7, 8]
})
# 用字典指定每列的填充值(A列填充0,B列填充100)
df_filled = df.fillna({'A': 0, 'B': 100})
print(df_filled)

- 前向填充(Forward Fill)——用前一个有效值填充
df_filled = df.fillna(method='ffill')
print(df_filled)
"""
A B
0 1.0 5.0
1 2.0 5.0
2 2.0 7.0
3 4.0 8.0
"""
- 后向填充(Backward Fill)——用后一个有效值填充
df_filled = df.fillna(method='bfill')
print(df_filled)
"""
A B
0 1.0 5.0
1 2.0 7.0
2 4.0 7.0
3 4.0 8.0
"""
- 用列的均值/中位数/众数填充
# 用每列的均值填充
df_filled = df.fillna(df.mean())
print(df_filled)
在填充前,通常先查看哪些地方有缺失:
# 查看每列缺失值数量 print(df.isnull().sum()) # 查看整个 DataFrame 的缺失情况 print(df.isnull())
7、文件读取与存储
我们的数据大部分存在于文件当中,所以pandas会支持复杂的IO操作,pandas的API支持众多的文件格式,如CSV、SQL、XLS、JSON、HDF5。
注:最常用的HDF5和CSV文件
pandas.read_csv(filepath_or_buffer, sep =',', usecols )- filepath_or_buffer:文件路径
- sep :分隔符,默认用","隔开
- usecols:指定读取的列名,列表形式
# 读取文件,并且指定只获取'open', 'close'指标
data = pd.read_csv("./KuangStudy_Data/01_stock_day.csv", usecols=['open', 'close'])

-
DataFrame.to_csv(path_or_buf=None, sep=', ’, columns=None, header=True, index=True, mode='w', encoding=None):保存文件- path_or_buf :文件路径
- sep :分隔符,默认用","隔开
- columns :选择需要的列索引
- header :boolean or list of string, default True,是否写进列索引值
- index:是否写进行索引
- mode:‘w’:重写, ‘a’ 追加
-
举例:保存读取出来的股票数据
- 保存’open’列的数据,然后读取查看结果
# 选取10行数据保存,便于观察数据
data[:10].to_csv("./KuangStudy_Data/02_stock_save.csv", columns=['open'])

会发现将索引(也就是时间)存入到文件当中,变成单独的一列数据。如果需要删除,可以指定index参数,删除原来的文件,重新保存一次。
# index:存储不会将索引值变成一列数据
data[:10].to_csv("./KuangStudy_Data/02_stock_save.csv", columns=['open'], index=False)

7.1、HDF5
7.1.1、read_hdf与to_hdf
HDF5文件的读取和存储需要指定一个键,值为要存储的DataFrame
pandas.read_hdf(path_or_buf,key =None,** kwargs):从h5文件当中读取数据- path_or_buffer:文件路径
- key:读取的键
- return:Theselected object
DataFrame.to_hdf(path_or_buf, key, ** kwargs)
# 读取文件
day_close = pd.read_hdf("./KuangStudy_Data/02_day_close.h5")

- 存储文件
# 存储的时候需要给个key
day_close.to_hdf("./KuangStudy_Data/02_day_close_save.h5", key="day_close")
再次读取的时候, 需要指定键的名字
new_close = pd.read_hdf("./data/test.h5", key="day_close")
注意:优先选择使用HDF5文件存储
- HDF5在存储的时候支持压缩,使用的方式是blosc,这个是速度最快的也是pandas默认支持的
- 使用压缩可以提磁盘利用率,节省空间
- HDF5还是跨平台的,可以轻松迁移到hadoop 上面
7.2、JSON
pandas.read_json(path_or_buf=None, orient=None, typ='frame', lines=False):将JSON格式准换成默认的Pandas DataFrame格式- path_or_buf: json文件的路径
- orient
- split:index -> [index], columns -> [columns], data -> [values]。split 将索引总结到索引,列名到列名,数据到数据。将三部分都分开了
- records:records 以
columns:values的形式输出 - index:ndex 以
index:{columns:values}...的形式输出 - columns:colums 以
columns:{index:values}的形式输出 - values:values 直接输出值
- typ : default ‘frame’, 指定转换成的对象类型series或者dataframe
- lines : boolean, default False。按照每行读取json对象
# orient指定存储的json格式,lines指定按照行去变成一个样本
json_read = pd.read_json("./KuangStudy_Data/03_Dataset.json", orient="records", lines=True)
其中03_Dataset.json里面的数据如下:


DataFrame.to_json(path_or_buf=None, orient=None, lines=False): 将Pandas 对象存储为json格式- path_or_buf=None:文件地址
- orient:存储的json形式,{‘split’,’records’,’index’,’columns’,’values’}
- lines:一个对象存储为一行
# 存储文件
json_read.to_json("./KuangStudy_Data/03_Dataset_save.json", orient='records')
更多推荐
所有评论(0)