四、Pandas数据处理
Pandas 数据处理
(一)Pandas库简介
1. Pandas
Pandas是一个开源的、用于数据处理和分析的Python库,特别适合处理表格类数据。它建立在NumPy 数组之上,提供了高效的数据结构和数据分析工具,使得数据操作变得更加简单、便捷和高效。
2. 核心
(1)数据结构
Series:一维数组,可以存储任何数据类型(整数、字符串、浮点数等),每个元素都有一个与之对应的标签(索引)。
DataFrame:二维表格型数据结构,可以视为多个 Series 对象的集合,每一列都是一个 Series。 每列可以有不同的数据类型,并且有行和列的标签。
(2)数据操作
读取和保存数据:支持多种数据格式,如 CSV、Excel、SQL 数据库、JSON 等。
数据选择和过滤:提供灵活的索引和条件筛选功能,方便数据的提取和过滤。
数据清洗:提供了处理缺失数据、重复数据、异常值等数据清洗功能。
数据转换:通过 apply() , map() , replace() 等方法进行数据转换。
数据合并:使用 concat() , merge() , join() 等方法进行数据的横向和纵向合并。
聚合和分组:使用 groupby() 结合 agg() , transform() 等方法进行数据的分组和聚合。
3. 主要特点
数据结构:Pandas提供了两种主要的数据结构:Series(一维数组)和DataFrame(二维表 格)。
数据操作:支持数据的增、删、改、查等操作,以及复杂的数据转换和清洗。
数据分析:提供丰富的数据分析方法,如聚合、分组、透视等。
文件读取与写入:支持多种文件格式(如CSV、Excel、SQL等)的读取和写入。
与其他库集成良好:Pandas 与许多其他三方库(如 NumPy、Matplotlib、Scikit-learn等)无缝集成,形成了一个强大的数据科学生态系统。
强大的社区支持:Pandas 拥有庞大的开发者社区,提供丰富的资源和学习材料。
4. Pandas的安装
Pandas是一个第三方库,并不属于Python的系统库,需要进行安装,可输入以下命令进行安装:
pip install pandas
(二)一维数组 Series
一维数组可以理解为excel中的一列数据:
标签 -- 可以是默认的,也可以是指定的

1. Series的创建
在Pandas中,一维数组的创建离不开Pandas库中的Series类。
class pandas.Series(data=None, index=None, dtype=None, name=None, copy=None, fastpath=False)
data:可以是以下几种类型的数据:
- 标量值,如整数或字符串
- Python列表或元组
- Python字典
- 1d-Ndarray
index:数组或列表,用于定义Series的索引。如果未提供,则默认为从0开始的整数索引。
dtype:指定Series的数据类型。
name:给Series一个名字,用于后续的索引和操作。
copy:布尔值,默认为False【新版本的若指定索引了,会强制复制,即copy=True】。如果为True,则复制数据;如果为False,则尽可能避免复制数据, 仅影响Ndarray输入。
fastpath:布尔值,默认为False,通常不需要用户指定。它是Pandas库内部使用的一个优化标 志,当设置为 True 时,允许 Series 构造函数绕过一些检查和验证步骤,加快Series的创建速度。 但由于这个参数跳过了某些安全检查,因此在正常使用中,如果在创建Series时设置了fastpath=True ,而传入的数据又不符合预期,则可能会导致不可预测的行为或错误。
(1)使用标量创建
import pandas as pd
# 定义一个变量 data,并赋值为5
data = 5
# 使用 pandas 库的 Series 函数创建一个 Series 对象
# 第一个参数是要作为 Series 数据的值,这里是 0
# 第二个参数必须是一个列表或数组,用于指定 Series 的索引,这里指定了索引为 ['a', 'b', 'c']
series = pd.Series(data, index=['a', 'b', 'c'])
# 打印输出创建好的Series对象
print(series)
print(type(series))
series = pd.Series(data, index=['A', 'b', 'c'], name='test')
# 打印输出创建好的Series对象
print(series)
print(type(series))
series = pd.Series(data, index=['A', 'B', 'c'], name='test2', dtype=str)
# 打印输出创建好的Series对象
print(series)
print(type(series))
运行结果:
a 5
b 5
c 5
dtype: int64
A 5
b 5
c 5
Name: test, dtype: int64
A 5
B 5
c 5
Name: test2, dtype: str
(2)使用列表或元组创建
import pandas as pd
# 定义一个列表 data1,其中包含了整数 1 到 5
data1 = [1, 2, 3, 4, 5]
# 定义一个元组 data2,其中包含了整数 5 到 1
data2 = (5, 4, 3, 2, 1)
# 使用 pandas 库的 Series 函数创建第一个 Series 对象 series1
# 第一个参数 data1 是要作为 Series1 数据的值,即列表[1, 2, 3, 4, 5]
# 第二个参数是一个列表 ['a', 'b', 'c', 'd', 'e'],用于指定 Series1 的索引
series1 = pd.Series(data1, index=['a', 'b', 'c', 'd', 'e'])
# 使用 pandas 库的 Series 函数创建第二个 Series 对象 series2
# 第一个参数 data2 是要作为 Series2 数据的值,即元组(5, 4, 3, 2, 1)
# 第二个参数是一个列表 ['a', 'b', 'c', 'd', 'e'],用于指定 Series2 的索引
series2 = pd.Series(data2, index=['a', 'b', 'c', 'd', 'e'])
# 打印输出创建好的第一个 Series 对象 series1
print(series1)
# 打印输出创建好的第二个 Series 对象 series2
print(series2)
运行结果:
a 1
b 2
c 3
d 4
e 5
dtype: int64
a 5
b 4
c 3
d 2
e 1
dtype: int64
(3)使用字典创建
使用字典创建 Series 时,字典的键就是索引,字典的值就是该索引对应的值。如果使用字典创建 Series,并且指定了与字典的键不同的 index 参数,那么生成的 Series 数组中的数据就是以 index 参数的值为索引,但索引所对应的值是 NaN。 在 Pandas 中, NaN (Not a Number)是一个特殊的浮点数,用于表示缺失数据或无效数据。 NaN 是 IEEE 浮点标准的一部分,Pandas 使用 NaN 来表示数据集中缺失或未定义的值。
import pandas as pd
# 定义一个字典 data,其中包含了三个键值对,键分别为'a'、'b'、'c',对应的值分别为1、2、3
data = {'a': 1, 'b': 2, 'c': 3}
# 使用 pandas 库的 Series 函数创建一个 Series 对象。
# 当传入一个字典作为参数时,字典的键会自动成为 Series 的索引,字典的值会成为对应索引下的数值。
series = pd.Series(data)
# 打印输出创建好的Series对象
print(series)
# 若依旧指定了与字典的键不同的 index 参数,则会以 index 参数的值为索引,但索引所对应的值全为 NaN
# 只要指定了 index 参数,无论指定多少个参数都会返回指定数量的 NaN,不会输出字典的值
series = pd.Series(data, index=['x', 'y', 'z'])
series2 = pd.Series(data, index=['x', 'y'])
# 打印输出创建好的Series对象
print(series)
print(series2)
运行结果:
a 1
b 2
c 3
dtype: int64
x NaN
y NaN
z NaN
dtype: float64
x NaN
y NaN
dtype: float64
(4)使用Ndarray创建
import pandas as pd
import numpy as np
# 使用 numpy 的 array 函数创建一个一维数组 data,数组中包含了整数 1 到 5
data = np.array([1, 2, 3, 4, 5])
# 使用 pandas 库的 Series 函数创建一个 Series 对象
# 传入刚刚创建的一维 numpy 数组 data 作为参数,此时会将该数组的数据依次作为 Series 的数值
# 并且会自动生成一个默认的整数索引(从 0 开始,依次递增,与数组元素的下标对应)
# 自定义索引会强制复制,即 copy=True
series = pd.Series(data,index=['a', 'b', 'c', 'd', 'e'],copy=False)
# 新版本的 panda,使用 series[0] 会添加元素,而不会将 series[0] 按位置索引工作
# series[0] = 100
series.iloc[0] = 100
# 打印输出创建好的 Series 对象,以便查看其具体内容,包括索引和对应的数据值等信息。
print(series)
print(data)
运行结果:
a 100
b 2
c 3
d 4
e 5
dtype: int64
[100 2 3 4 5]
2. Series的属性(16)
(1)index
返回Series中的索引,可赋值修改
import pandas as pd
# 创建 Series 数组
series = pd.Series([1, 2, 3], index=['a', 'b', 'c'])
# 打印输出该 Series 对象的索引。
# Series 对象的 index 属性可以获取到它的索引信息,这里会输出索引 -- ['a', 'b', 'c']。
print(series.index)
# 重新给 Series 对象的索引赋值。
# 将原来的索引 -- ['a', 'b', 'c'],修改为新的索引 -- ['e', 'f', 'g'],
# 这会改变 Series 对象中每个数据元素对应的索引标识。
series.index = ['e', 'f', 'g'] # 数量必须一一对应,不能少,不能多
# 再次打印输出修改索引后的 Series 对象,
print(series)
运行结果:
Index(['a', 'b', 'c'], dtype='str')
e 1
f 2
g 3
dtype: int64
(2)values
只读属性,用于返回Series中的数据,返回的数据将以Ndarray数组的形式存在。
import pandas as pd
# 创建 Series 数组
series = pd.Series([1, 2, 3], index=['a', 'b', 'c'])
# 打印输出该 Series 对象的数据。
print(series.values)
print(type(series.values))
# # values无法通过直接赋值的方式去修改
# series.values = ['e', 'f', 'g']
# print(series)
运行结果:
[1 2 3]
(3)name
用于返回Series的名称,如果创建时指定了name参数,那么该属性的返回值就是name参数,如果没有指定则为None,可赋值修改
import pandas as pd
# 创建 Series 数组
series = pd.Series([1, 2, 3], index=['a', 'b', 'c'])
# 打印输出该 Series 对象的name属性值。
print(series.name)
# 给 Series 对象的 name 属性赋值为 'test'。
# 这相当于给这个 Series 对象起了一个名字,方便在后续处理或展示数据时进行识别和区分。
series.name = 'test'
# 再次打印输出该 Series 对象的 name 属性值,
print(series.name)
运行结果:
None
test
(4)dtype和dtypes
对于Series来说,dtype和dtypes的作用是一样的,都是用来返回Series对象的数据类型。
需要注意的是:属性都为只读属性,不可以通过直接赋值的方式去修改数据类型。
import pandas as pd
# 创建 Series 数组
series = pd.Series([1, 2, 3], index=['a', 'b', 'c'])
# 打印输出该 Series 对象的数据类型。
# Series 对象的 dtype 属性可以获取到其数据的类型,这里创建的 Series 数据是整数类型,所以会输出 'int64'。
print(series.dtype)
# Series 对象的 dtype 属性是只读属性,不可以直接通过赋值的方式来改变数据类型。
# 要改变 Series 对象的数据类型,需要使用 astype 等合适的方法来进行转换操作。
# series.dtype = 'float32'
# print(series.dtype)
(5)shape
用于描述Series的形状,该返回值是一个元组。
import pandas as pd
import numpy as np
# 创建 Series 数组
series = pd.Series([1, 2, 3], index=['a', 'b', 'c'])
arr = np.array([1,2,3])
# 打印数组的形状
print(series.shape)
print(arr.shape)
运行结果:
(3,)
(3,)
(6)size
用于返回Series的元素数量,该返回值是一个整数。
import pandas as pd
# 创建 Series 数组
series = pd.Series([1, 2, 3], index=['a', 'b', 'c'])
# 打印数组元素的元素数量
print(series.size) # 打印:3
(7)empty
用来表示Series数组是否为空,返回值一个布尔值
如果数组里一个元素都没有就返回True,否则返回 False。
import pandas as pd
# 创建Series数组
series = pd.Series()
series2 = pd.Series([1,2,3])
# 判断数组是否为空
print(series.empty) # True
print(series2.empty) # False
(8)hasnans
用于返回数组中是否包含NaN值,如果数组中存在NaN,那么返回True,否则返回False。
import pandas as pd
import numpy as np
# 创建 Series 数组
# 用 numpy 下的 nan 替代无效,缺失数据
series = pd.Series([1, 2, 3, np.nan], index=['a', 'b', 'c', 'd'])
series2 = pd.Series([np.nan]) # 是空值,但不代表数组为空
# 判断数组是否存在 NaN 值
print(series)
print(series.hasnans) # True
print(series2.empty) # False
(9)is_unique
用于返回数组中的元素是否为独一无二的,如果所有的元素都是独一无二的,即数组中没有重复元素, 那么就返回True,否则返回False。
import pandas as pd
# 创建 Series 数组
series = pd.Series(['a', 'b', 'c'])
# 判断数组中是否存在重复的元素
print(series.is_unique) # True
(10)nbytes
用于返回该 Series 对象中所有数据占用的总字节数。
import pandas as pd
# 创建 Series 数组
series = pd.Series([1, 2, 3, 4, 5], dtype='int64')
# 获取数组元素所占用的内存大小
print(series.nbytes) # 40
(11)axes
用于返回 series 对象行轴标签的列表。
和 index 差不多
import pandas as pd
# 创建 Series 数组
series = pd.Series([1, 2, 3, 4, 5], index=['a', 'b', 'c', 'd', 'e'], dtype='int64')
# 获取数组的行轴标签
print(series.axes) # [Index(['a', 'b', 'c', 'd', 'e'], dtype='str')]
(12)ndim
返回 Series 数组的维度,对于Series数组来说,它的维度始终为1。
import pandas as pd
# 创建 Series 数组
series = pd.Series([1, 2, 3, 4, 5], index=['a', 'b', 'c', 'd', 'e'], dtype='int64')
# 获取数组的索引
print(series.ndim) # 1
(13)array
用于返回 Series 的底层数组,包括数组的元素、数组的长度及数组元素的数据类型。
import pandas as pd
import numpy as np
# 创建一个 NumPy 数组
data = np.array([1, 2, 3, 4, 5])
# 使用 NumPy 数组创建一个 Pandas Series
series = pd.Series(data)
# 打印 Series 的底层数据作为一个 Pandas 的 Array 对象
print(series.array)
# 打印上述 Array 对象的类型
print("\n",type(series.array))
运行结果:
[1, 2, 3, 4, 5]
Length: 5, dtype: int64
(14)attrs
返回 series 的自定义属性,可以用来存储额外的说明性数据。
import pandas as pd
# 创建一个包含整数 1 到 5 的 Pandas Series
series = pd.Series([1, 2, 3, 4, 5])
# 打印额外的属性
print(series.attrs,"\n")
# 给 Series 添加额外的属性,这里添加了来源和时间信息
series.attrs = {'source': 'file1', 'time': '19:27:27'}
# 打印 Series 本身,将显示其数据和索引
print(series)
# 打印 Series 的额外属性
print('\n额外属性', series.attrs)
运行结果:
{}
0 1
1 2
2 3
3 4
4 5
dtype: int64
额外属性 {'source': 'file1', 'time': '19:27:27'}
(15)is_monotonic_decreasing
返回一个布尔值,表示 Series 是否按降序排列。
import pandas as pd
# 创建一个 Pandas Series,其值从 5 递减到 1
series = pd.Series([5, 4, 3, 2, 1])
# 打印检查 Series 是否单调递减的结果
# 由于 Series 中的值是递减的,所以这个表达式将返回 True
print(series.is_monotonic_decreasing)
(16)is_monotonic_increasing
返回一个布尔值,表示 Series 是否按升序排列。
import pandas as pd
# 创建一个 Pandas Series,其值从 1 递增到 5
series = pd.Series([1, 2, 3, 4, 5])
# 打印检查 Series 是否单调递增的结果
# 由于 Series 中的值是递增的,所以这个表达式将返回 True
print(series.is_monotonic_increasing)
3. Series中元素的索引与访问
(1)位置索引
可以使用整数索引来访问Series中的元素,就像访问列表一样。
import pandas as pd
# 创建一个 Series
series = pd.Series([10, 20, 30, 40, 50])
# 通过位置索引获取元素
print(series[0])
print(series[2])
(2)标签索引
除了使用位置索引之外,还可以使用标签进行索引,与访问字典中的元素类似。
import pandas as pd
# 创建一个带有标签的 Series
series = pd.Series([10, 20, 30, 40, 50], index=['a', 'b', 'c', 'd', 'e'])
# 通过标签索引获取元素
print(series['a'])
print(series['c'])
(3)切片索引
Series对象的切片方式有两种,第一种是使用位置切片,其使用方法与列表的切片类似;第二种是使用标签切片,其语法与位置切片类似,都是 start:stop ,且开始值与终止值可以省略,但与位置切片不同的是,标签切片的范围是左右都闭合,即既包含start,又包含stop,而位置切片是左闭右开,只包含 start,不包含stop。
import pandas as pd
# 创建一个带有标签的 Series
series = pd.Series([10, 20, 30, 40, 50], index=['a', 'b', 'c', 'd', 'e'])
# 通过位置切片
print(series[:])
# 通过标签切片
print(series['b':'d'])
(4)loc与iloc
loc与iloc也是Series对象的属性,它们的作用就是用来访问Series中的元素
loc是基于标签的索引,iloc 是基于切片、位置的索引。
import pandas as pd
# 创建一个带有标签的 Series
series = pd.Series([10, 20, 30, 40, 50], index=['a', 'b', 'c', 'd', 'e'])
# 使用 .loc 通过标签索引
print(series.loc['a'])
# 使用 .iloc 通过切片、位置索引
print(series.iloc[0:2])
print(series.iloc[2])
运行结果:
10
a 10
b 20
dtype: int64
30
(5)at与iat
at 与 iat 也是Series对象的属性,可以用来访问元素
at 是基于标签的索引,iat是基于位置的索引
import pandas as pd
# 创建一个带有标签的 Series
series = pd.Series([10, 20, 30, 40, 50], index=['a', 'b', 'c', 'd', 'e'])
# 使用 .at 通过标签索引
print(series.at['a'])
# 使用 .iat 通过位置索引
print(series.iat[0])
print(series.iat[2])
(6)head
head 是 Series 对象的方法,用于快速查看 Series 数据的开头部分内容
series.head(n=None)
n:是可选参数,用于指定要返回的行数。如果不提供该参数,默认值为 5 。
import pandas as pd
# 创建一个 Series 对象
data = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
index = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
series = pd.Series(data, index=index)
# 使用 head 函数查看前 5 行数据
print(series.head())
(7)tail
tail的用法与head类似,但不同的是,它用于快速查看 Series 数据的末尾部分内容
series.tail(n=None)
n:是可选参数,用于指定要返回的行数。若不提供该参数,默认值为 5 。
import pandas as pd
# 创建一个 Series 对象
data = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
index = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
series = pd.Series(data, index=index)
# 使用 tail 函数查看后 5 行数据
print(series.tail())
(8)isin
该函数用于判断 Series 中的每个元素是否在指定的一组值中
返回一个与原 Series 长度相同的布尔型 Series ,其中对应位置为 True 表示该位置的元素在指定的值集合中, False 则表示不在
series.isin(values)
values:是一个可迭代对象(如列表、元组、集合等),用于指定要进行判断的一组值。
import pandas as pd
# 创建一个 Series 对象(被检查的值)
data = [10, 20, 30, 40, 50]
series = pd.Series(data)
# 指定要判断的一组值(要检查的值)
values_to_check = [20, 40]
# 使用 isin 函数进行判断 -- 判断 series 是否在 values_to_check 中
result = series.isin(values_to_check)
print(result)
(9)get
Series.get 方法用于通过标签来获取 Series 中的元素。
Series.get(key, default=None)
key: 你想要获取的元素的标签。
default: 可选参数,如果 key 不在标签中,返回这个默认值。如果没有指定,默认为 None 。
import pandas as pd
# 创建一个示例 Series
s = pd.Series(['apple', 'banana', 'cherry'], index=[1, 2, 3])
# 使用 get 方法获取元素
print(s.get(2))
print(s.get(4, 'Not Found'))
4. 数据操作
(1)数据清洗
数据清洗指对 Series 对象中的某些值进行删除、修改等操作,分别使用以下方法:
dropna():删除包含NaN值的行。
series.dropna(axis=0, inplace=False)
axis:可选参数,用于指定按哪个轴删除缺失值。对于 Series 对象,因为它是一维数据结构, 只有一个轴,所以此参数默认值为 0 ,且一般不需要修改这个参数(在处理DataFrame时该参数 才有更多实际意义,如 axis = 0 表示按行删除, axis = 1 表示按列删除)。
inplace:可选参数,用于指定是否在原 Series 对象上进行操作。如果inplace = True,则会 直接在原 Series 上删除缺失值,原 Series 会被修改;如果inplace = False(默认值),则会 返回一个删除了缺失值的新 Series ,原 Series 保持不变。
import pandas as pd
import numpy as np
# 创建一个包含缺失值的 Series 对象
data = [1, np.nan, 3, 4, np.nan]
series = pd.Series(data)
# 使用 dropna 函数删除缺失值,返回新的 Series
new_series = series.dropna()
print(new_series)
fillna():填充NaN值。
Series.fillna(value=None, method=None, axis=None, inplace=False, limit=None, downcast=None)
pandas 的新版本(2.1+)中 fillna() 的 method 参数已被弃用。
现在应该使用专门的方法:(只有向前、向后填充改了)
- 前向填充: ffill() 或 fillna(method='ffill') → 改为 ffill()
- 后向填充: bfill() 或 fillna(method='bfill') → 改为 bfill()
value :用于填充缺失值的标量值或字典。如果传递的是字典,则字典的键应该是要填充的标签,值是用于填充的值。
method :字符串,表示填充的方法。可选值包括:
- pad / ffill :用前一个非缺失值去填充缺失值。
- bfill / backfill :用后一个非缺失值去填充缺失值。
axis :填充的轴,对于 Series 对象来说,这个参数通常不需要指定,因为 Series 是一维的。
inplace :布尔值,表示是否在原地修改数据。如果为 True ,则直接在原 Series 上修改,不返回新的对象。
limit :整数,表示最大填充量。如果指定,则只填充前 limit 个缺失值。
downcast :字典,用于向下转换数据类型。例如,可以将 float64 转换为 float32 。
import pandas as pd
import numpy as np
# 创建一个包含缺失值的 Series
s = pd.Series([1, np.nan, 3, np.nan, 5])
print(f"初始数组:\n{s}")
# 使用标量值填充
filled_with_scalar = s.fillna(0)
print(f"\n使用标量值填充:\n{filled_with_scalar}")
# 使用字典填充 -- 字典的键要属于标签(显式声明类型转换)
# 先把 Series 转成 object 类型,让 Pandas 明确知道要容纳混合类型
# 否则会报错:Pandas4Warning: 'ndarray' is not supported as a fill value for float64 dtype. In a future version, calling fillna with an incompatible value will raise. Explicitly cast to a common dtype before filling.
s = s.astype('object')
filled_with_dict = s.fillna({1:2,3:"a"})
print(f"\n使用字典填充:\n{filled_with_dict}")
# 使用前向填充
filled_with_ffill = s.ffill()
print(f"\n使用向前填充:\n{filled_with_ffill}")
# 使用后向填充
filled_with_bfill = s.bfill()
print(f"\n使用向后填充:\n{filled_with_bfill}")
# 使用 limit 参数
filled_with_limit = s.fillna(value=0, limit=1)
print(f"\n使用 limit 参数:\n{filled_with_limit}")
运行结果:
初始数组:
0 1.0
1 NaN
2 3.0
3 NaN
4 5.0
dtype: float64
使用标量值填充:
0 1.0
1 0.0
2 3.0
3 0.0
4 5.0
dtype: float64
使用字典填充:
0 1.0
1 2
2 3.0
3 a
4 5.0
dtype: object
使用向前填充:
0 1.0
1 1.0
2 3.0
3 3.0
4 5.0
dtype: object
使用向后填充:
0 1.0
1 3.0
2 3.0
3 5.0
4 5.0
dtype: object
使用 limit 参数:
0 1.0
1 0
2 3.0
3 NaN
4 5.0
dtype: object
isnull():检测 Series 对象中的缺失值,它会返回一个布尔型 Series,其中每个元素表示原 Series 对应位置的值是否为缺失值(NaN)。
Series.isnull()
import pandas as pd
import numpy as np
# 创建一个包含缺失值的Series
s = pd.Series([1, 2, np.nan, 4, np.nan])
print(f"初始化:\n{s}")
# 使用isnull()方法检测缺失值
missing_values = s.isnull()
# 输出结果
print(f"\nisnull():\n{missing_values}")
运行结果:
初始化:
0 1.0
1 2.0
2 NaN
3 4.0
4 NaN
dtype: float64
isnull():
0 False
1 False
2 True
3 False
4 True
dtype: bool
drop_duplicates():用于去除 Series 对象中的重复项。
Series.drop_duplicates(keep='first', inplace=False, ignore_index=False)
keep:可选参数,决定了如何处理重复项。有三个选项:
- 'first' :默认值,保留第一次出现的重复项。
- 'last' :保留最后一次出现的重复项。
- False :不保留任何重复项,即删除所有重复项。
inplace :布尔值,默认为 False 。如果设置为 True ,则直接在原始Series上进行操作,返回值 为 None 。如果设置为 False ,则返回一个新的Series,不修改原始Series。
ignore_index :布尔值,默认为 False 。如果设置为 True ,则结果的索引将被重新设置,以反 映删除重复项后的新顺序。如果设置为 False ,则保留原始索引。
import pandas as pd
series = pd.Series(['a', 'b', 'b', 'c', 'c', 'c', 'd'])
print(f"初始数组:\n{series}")
print("\n保留第一个:")
series_unique = series.drop_duplicates(keep='first')
print(series_unique)
print("\n保留最后一个:")
series_unique = series.drop_duplicates(keep='last')
print(series_unique)
print("\n不保留:")
series_unique = series.drop_duplicates(keep=False)
print(series_unique)
运行结果:
初始数组:
0 a
1 b
2 b
3 c
4 c
5 c
6 d
dtype: str
保留第一个:
0 a
1 b
3 c
6 d
dtype: str
保留最后一个:
0 a
2 b
5 c
6 d
dtype: str
不保留:
0 a
6 d
dtype: str
(2)数据转换
replace():替换特定的值、一系列值或者使用字典映射进行替换。
Series.replace(to_replace=None, value=None, inplace=False, limit=None, regex=False, method='pad')
to_replace :要替换的值,可以是以下类型:
- 标量:单个值。
- 列表:一系列值。
- 字典:键是要替换的值,值是替换后的新值。
- 正则表达式:如果 regex=True ,则可以使用正则表达式匹配要替换的值。
value :替换后的新值,可以是标量或字典。如果 to_replace 是列表,则 value 也应该是相同 长度的列表。
inplace :布尔值,表示是否在原地修改数据。如果为 True ,则直接在原 Series 上修改,不 返回新的对象。
limit :整数,表示最大替换量。如果指定,则只替换前 limit 个匹配的值。
regex :布尔值,表示是否将 to_replace 解释为正则表达式。
method :字符串,表示填充的方法,在 to_replace 参数是一个标量、列表或元组,同时 value 参数设置为 None 时,可以使用 method 参数来指定填充缺失值(NaN)的方式。可选值包括:
- pad / ffill :用前一个非缺失值去填充缺失值。
- bfill :用后一个非缺失值去填充缺失值。
import pandas as pd
# 创建一个 Series
s = pd.Series([1, 2, 3, 4, 5])
# 进行替换操作
replaced = s.replace(to_replace=2, value=20)
print(replaced)
astype():用于将 Series 的数据类型(dtype)转换或转换为另一种类型。
Series.astype(dtype, copy=True, errors='raise')
dtype:你希望将 Series 转换成的数据类型。
copy:布尔值,默认为 True 。如果为 False ,则转换数据类型时不会复制底层数据(如果可能 的话)。
errors:默认为 ‘raise’,控制当转换失败时的行为。如果设置为 ‘raise’,则在转换失败时会抛出异 常;如果设置为 ‘ignore’,转换失败后则返回原始 Series ,不做任何修改。
import pandas as pd
s = pd.Series([1, 2, 3, 4, 5])
# 将整数转换为字符串
s_str = s.astype(float)
print(s_str)
s = pd.Series(["a","b","c"])
# 将字符串转换为整数 -- ignore 忽略错误,返回原数据;raise 抛出错误
s_int = s_str.astype(int,errors="ignore")
print(s_int)
transform():用于对 Series 中的数据进行转换操作,并返回与原始 Series 具有相同索引的新 Series
Series.transform(func, axis=0, *args, **kwargs)
func : 应用于Series的函数。这个函数可以是内置函数,或者自定义的函数。
axis : 对于Series来说,这个参数不起作用,因为Series是一维的。在DataFrame上使用时, axis=0 (默认)表示按列应用函数, axis=1 表示按行应用函数。
*args, **kwargs : 这些参数会被传递给 func 函数。
import pandas as pd
# 自定义一个函数,返回每个元素的平方
def square(x, y):
print(y)
return x ** 2
# 创建一个Series
s = pd.Series([1, 2, 3, 4, 5])
# 使用自定义函数对Series进行平方变换
transformed_series = s.transform(square,y="yyy")
print(transformed_series)
运行结果:
yyy
yyy
yyy
yyy
yyy
0 1
1 4
2 9
3 16
4 25
dtype: int64
(3)数据排序
sort_values():按照值对 Series 进行排序
Series.sort_values(axis=0, ascending=True, inplace=False, kind='quicksort', na_position='last', ignore_index=False, key=None)
axis:默认为 0。对于 Series,这个参数不起作用,因为 Series 是一维的,而 sort_values 总是 在 axis=0 上操作。
ascending:布尔值,默认为 True 。如果是 True ,则按照升序排列;如果是 False ,则按照降序排列。
inplace:布尔值,默认为 False 。如果为 True ,则排序将直接在原始 Series 上进行,不返回新的 Series。
kind:排序算法,{‘quicksort’, ‘mergesort’, ‘heapsort’, ‘stable’},默认为 ‘quicksort’。决定了使用的排序算法。
na_position:{‘first’, ‘last’},默认为 ‘last’。这决定了 NaN 值的放置位置。
ignore_index:布尔值,默认为 False 。如果为 True ,则排序后的 Series 将重置索引,使其成为默认的整数索引。
key:函数,默认为 None 。如果指定,则这个函数将在排序之前应用于每个值,并且排序将基于这些函数返回的值。
import pandas as pd
import numpy as np
def square(x):
return x**2
s = pd.Series([-3, 1, 4, 1, np.nan, 9],index=['a', 'b', 'c', 'd', 'e', 'f'])
print(f"初始数组:\n{s}")
# 排序并重置索引,默认升序,NaN 值放最后
sorted_s = s.sort_values()
print(f"\n按照值升序排序:\n{sorted_s}")
sorted_s = s.sort_values(ascending=False,na_position='first') # first为字符串,要加引号
print(f"\n按照值降序排序,NaN 值放开头:\n{sorted_s}")
sorted_s = s.sort_values(ignore_index=True,key=square)
print(f"\n重置索引,以函数square的返回值升序排序:\n{sorted_s}")
运行结果:
初始数组:
a -3.0
b 1.0
c 4.0
d 1.0
e NaN
f 9.0
dtype: float64
按照值升序排序:
a -3.0
b 1.0
d 1.0
c 4.0
f 9.0
e NaN
dtype: float64
按照值降序排序,NaN 值放开头:
e NaN
f 9.0
c 4.0
b 1.0
d 1.0
a -3.0
dtype: float64
重置索引,以函数square的返回值升序排序:
0 1.0
1 1.0
2 -3.0
3 4.0
4 9.0
5 NaN
dtype: float64
sort_index():按照索引的顺序对数据进行排序。
Series.sort_index(axis=0, level=None, ascending=True, inplace=False, kind='quicksort', na_position='last', sort_remaining=True, ignore_index=False, key=None)
axis : 默认为0,对于 Series,这个参数不起作用。
level : 默认为 None,如果索引是多级索引(也称为层次化索引或 MultiIndex),则可以指定要排序的级别。
ascending : 默认为 True,如果为 True,则按升序排序;如果为 False,则按降序排序。对于多级索引,可以传递一个布尔值列表,以指定每个级别的排序顺序。
inplace : 默认为 False,如果为 True,则直接在原对象上进行修改,不会返回一个新的对象。
kind : {‘quicksort’, ‘mergesort’, ‘heapsort’},默认为 ‘quicksort’,指定排序算法。‘quicksort’ 是最快的通用排序算法,但不是稳定的;‘mergesort’ 是稳定的,但可能比 ‘quicksort’ 慢;‘heapsort’ 是原地排序算法,但通常比其他两个选项慢。
na_position : {‘first’, ‘last’}, 默认为 ‘last’,指定 NaN 值应该排在排序结果的开头还是结尾。
sort_remaining : 默认为 True,对于多级索引,如果为 True,在该level排序后,在排序的基础上对剩下的级别的元素还会排序。
ignore_index : 默认为 False,如果为 True,则排序后的结果将不再保留原始索引,而是使用默认的整数索引。
key:函数,默认为 None 。如果指定,则这个函数将在排序之前应用于每个值,并且排序将基于这些函数返回的值。
import numpy as np
import pandas as pd
arrays = [np.array(['qux', 'qux', 'foo', 'foo','baz', 'baz', 'bar', 'bar']),
np.array(['two', 'one', 'two', 'one','two', 'one', 'two', 'one'])
]
# 默认:指定要排序的级别为 0,升序排序
s = pd.Series([1,2,3,4,5,6,7,8],index=arrays)
print(s)
print(s.shape)
# 指定要排序的级别为 1,升序排序,保留其他级别的顺序,不重置索引
res = s.sort_index(level=1,ascending=True,sort_remaining=True,ignore_index=False)
# res = s.sort_index()
print(res)
(4)数据筛选
可以使用一个布尔数组来选择满足条件的元素。
import pandas as pd
# 创建一个带有标签的Series
series = pd.Series([10, 20, 30, 40, 50], index=['a', 'b', 'c', 'd', 'e'])
# 选择大于30的元素
print(series[series > 30])
(5)数据拼接
concat():用于将多个Pandas对象(如Series或DataFrame)沿着一个轴连接起来的函数。
pandas.concat(objs, *, axis=0, join='outer', ignore_index=False, keys=None, levels=None, names=None, verify_integrity=False, sort=False, copy=None)
objs : 参与连接的Pandas对象的列表或元组。例如,可以是多个Series或DataFrame。
axis : {0或’index’, 1或’columns’},表示连接的轴,默认为0。0表示沿着行方向连接(索引轴), 1表示沿着列方向连接(列轴)。
join : {‘inner’, ‘outer’},默认为’outer’。如何处理其他轴上的索引。'outer’表示并集,保留所有索引;'inner’表示交集,只保留所有对象共有的索引。
ignore_index : 布尔值,默认为False。如果为True,则不保留原索引,而是创建一个新索引,可以避免重复的索引。
keys : 序列,默认为None。用于创建分层索引的键。如果提供了keys,则生成的DataFrame 或 Series将具有分层索引。
levels : 序列列表,默认为None。用于构造分层索引的特定级别,如果设置了keys,则默认为 keys。
names : 列表,默认为None。生成的分层索引中的级别名称。如果提供了keys,表示使用keys作为索引名称。
verify_integrity : 布尔值,默认为False。如果为True,则检查新连接的轴是否包含重复的索引,如果发现重复,则引发ValueError。这在确保数据没有重复时很有用。
sort : 布尔值,默认为False。在连接之前是否对非连接轴上的索引进行排序。这在连接多个 DataFrame 时很有用,可以确保索引是有序的。
copy : 布尔值,默认为None。如果为True,则不管是否需要,都会复制数据。如果为False,则尽量避免复制数据,除非必要。None表示自动选择。
import pandas as pd
# 创建三个Series
s1 = pd.Series([1, 2, 3], index=['a', 'b', 'c'])
s2 = pd.Series([4, 5, 6], index=['c', 'd', 'f'])
s3 = pd.Series([7, 8, 9], index=['e', 'f', 'g'])
# 使用concat连接Series
# 默认按行拼接,并集,保留所有索引,保留原索引,
result = pd.concat([s1, s2, s3])
print(result)
5. 统计计算
(1)count
用于计算 Series 中非 NaN(非空)值的数量
import pandas as pd
# 创建一个包含空值的Series
s = pd.Series([1, 2, None, 4, None])
# 使用count()函数计算非空值的数量
count_non_na = s.count()
print(count_non_na)
(2)sum
sum() 函数会计算所有值的总和
Series.sum(axis=None, skipna=True, numeric_only=None, min_count=0)
axis : 对于 Series 对象来说,这个参数通常不起作用,因为 Series 是一维的。它主要在 DataFrame 对象中用于指定操作的轴(0表示按列求和,1表示按行求和)
skipna : 布尔值,默认为 True 。如果为 True ,则在计算总和时会忽略 NaN 值,如果为False,则返回NaN
numeric_only : 布尔值,默认为 None 。如果为 True ,则只对数字类型的数据进行计算,只针对 DataFrame
min_count : int值,默认为0。表示在计算总和之前,至少需要多少个非 NaN 值。如果非 NaN 值的数量小于 min_count ,则结果为 NaN
import pandas as pd
s = pd.Series([1, 2, None, 4, 5])
total = s.sum(min_count=3) # 至少要 5 个非空值才计算总和
print(total)
total = s.sum(skipna=False) # 算总和时是否会忽略 NaN 值,默认忽略,若不忽略则返回 nan
print(total)
(3)mean
mean() 函数会计算所有值的平均值
Series.mean(axis=None, skipna=True, numeric_only=None)
axis : 对于 Series 对象来说,这个参数通常不起作用,因为 Series 是一维的。它主要在 DataFrame 对象中用于指定操作的轴(0表示按列计算平均值,1表示按行计算平均值)。
skipna : 布尔值,默认为 True 。如果为 True ,则在计算平均值时会忽略 NaN 值,如果为False, 则返回NaN。
numeric_only : 布尔值,默认为 None 。如果为 True ,则只对数字类型的数据进行计算,只针对 DataFrame。
# 计算所有值的平均值
import pandas as pd
s = pd.Series([1, 2, 3, None, 4, 5])
# 默认忽略空值
average = s.mean()
print(average)
# 不忽略空值,直接返回 nan
average = s.mean(skipna=False)
print(average)
(4)median
median() 函数用于计算 DataFrame 或 Series 中的中位数
Series.median(axis=0, skipna=True, numeric_only=False)
axis : 对于 Series 对象来说,这个参数通常不起作用,因为 Series 是一维的。它主要在 DataFrame 对象中用于指定操作的轴(0表示按列计算中位数,1表示按行计算中位数)。
skipna : 布尔值,默认为True。如果为True,则在计算中位数之前会排除NaN值,如果为False, 则返回NaN。
numeric_only : 布尔值,默认为 None 。如果为 True ,则只对数字类型的数据进行计算,只针对 DataFrame。
import pandas as pd
s = pd.Series([1, 2, 3, 4, 5])
median_value = s.median()
print(median_value)
(5)min和max
Series.min() 函数用于计算 Series 对象中的最小值, Series.max() 函数用于计算 Series 对象中的最大值。
Series.min(axis=0, skipna=True, numeric_only=False)
Series.max(axis=0, skipna=True, numeric_only=False)
axis : 对于 Series 对象来说,这个参数通常不起作用,因为 Series 是一维的。它主要在 DataFrame 对象中用于指定操作的轴(0表示按列计算最小值或最大值,1表示按行计算最小值或 最大值)。
skipna : 布尔值,默认为True。如果为True,则在计算最值之前会排除NaN值,如果为False,则返回NaN。
numeric_only : 布尔值,默认为 None 。如果为 True ,则只对数字类型的数据进行计算,只针对 DataFrame。
import pandas as pd
s = pd.Series([1, 2, 3, 4, 5])
min_value = s.min()
max_value = s.max()
print('最小值是:', min_value)
print('最大值是:', max_value)
(6)var
Series.var() 函数用于计算 Series 对象的方差。
axis : 对于 Series 对象,这个参数不会产生任何效果,因为 Series 是一维的。在 DataFrame 中, axis 用于指定沿着哪个轴计算方差。
skipna : 布尔值,默认为 True 。如果为 True ,则在计算方差之前会忽略 NaN 值。如果设置为 False ,计算方差时会包括 NaN 值,通常会导致结果也是 NaN 。
ddof : 整数,默认为 1 。Delta Degrees of Freedom,用于贝塞尔校正,以得到样本方差的估计。对于无偏估计(样本方差), ddof 通常设置为 1 。如果计算总体方差,应该将 ddof 设置为 0 。
numeric_only : 布尔值,默认为 False 。如果为 True ,则只对数字类型的数据进行方差计算,忽 略非数字类型的数据。
import pandas as pd
import numpy as np
s = pd.Series([1, 2, np.nan, 4, 5])
# ddof:贝塞尔校正,以得到样本方差的估计(默认为 1)
# 对于无偏估计(样本方差), ddof 通常设置为 1 ;如果计算总体方差,应该将 ddof 设置为 0
variance = s.var()
print('方差是:', variance)
(7)std
Series.std() 函数用于计算 Series 对象的标准差。
Series.std(axis=None, skipna=True, ddof=1, numeric_only=False, **kwargs)
axis : 对于Series来说,这个参数不会产生任何效果,因为Series是一维的。它主要用于 DataFrame,以指定沿着哪个轴计算标准差。
skipna : 布尔值,默认为True。如果为True,则在计算标准差之前会忽略NaN值,如果为False, 则返回NaN。
ddof : 整数,默认为1。Delta Degrees of Freedom,是贝塞尔校正的参数。对于无偏估计(样本 标准差),ddof通常设置为1。
numeric_only : 布尔值,默认为False。如果为True,则只对数字类型的数据进行计算,只针对 DataFrame。
**kwargs : 其他关键字参数。
import pandas as pd
import numpy as np
s = pd.Series([1, 2, np.nan, 4, 5])
std_dev = s.std()
print('标准差是:', std_dev)
(8)quantile
Series.quantile() 方法用于计算 Series 中数值的分位数。
Series.quantile(q=0.5, interpolation='linear')
q :这个参数是必需的,它表示要计算的分位数值。可以是单一的数值,也可以是一个数值列表。 例如, q=0.5 表示计算中位数(50%分位数)。
interpolation :这个参数决定了当所需的分位数位于两个数据点之间时,应该如何插值。默认 值是 'linear' ,表示线性插值。其他选项包括 'nearest' (最近的值)、 'lower' (选择较小 的值)、 'higher' (选择较大的值)、 'midpoint' (两个值的中间点)。
其计算过程为:
-
首先将Series中的所有非NaN元素按升序排序。
-
假设Series的长度为
n, 我们需要计算第q个分位数的位置下标index:
-
如果
index是一个整数, 则直接取该位置上的值; 如果index不是整数, 则需要进行插值计算。 -
根据不同的插值方法, 确定最终的分位数值:
-
linear(默认): 线性插值。假设index = i + f, 其中i是整数部分,f是小数部分。那么分位数为: \(Q = x_{i} + f \times (x_{i+1} - x_{i})\), 其中 \(x_{i}\) 和 \(x_{i+1}\) 是排序后的数据中第i和i+1个元素。 -
lower: 选择较小的那个值。即取 \(x_{i}\)。 -
higher: 选择较大的那个值。即取 \(x_{i+1}\)。 -
nearest: 选择最近的那个值。如果f <= 0.5, 取 \(x_{i}\), 否则取 \(x_{i+1}\)。 -
midpoint: 取这两个值的平均数, 即: \(Q = \frac{x_{i} + x_{i+1}}{2}\)。
-
import pandas as pd
# 创建一个示例Series
s = pd.Series([1, 2, 3, 4, 5])
# 计算0.5(中位数)分位数 -- q是必须的
median_value = s.quantile(q=0.5, interpolation='linear')
print(median_value)
(9)cummax
该方法用于计算 Series 中元素的累积最大值
返回一个相同长度的Series,其中每个位置上的值表示从Series开始到当前位置(包括当前位置)的最大值。
Series.cummax(axis=None, skipna=True, *args, **kwargs)
axis: 对于Series来说,这个参数不起作用,因为Series是一维的。在DataFrame上使用时,axis=0(默认)表示按列计算,axis=1表示按行计算。
skipna: 布尔值,默认为True。如果为True,则在计算累积最大值时会忽略NaN值;如果为False,则任何NaN值都会传播,并且会导致结果在该位置及之后的值都为NaN。
*args,**kwargs: 这些参数用于兼容性,通常不需要使用。
import pandas as pd
# 创建一个Series
s = pd.Series([2, 1, 3, 5, 4, 6])
# 计算累积最大值 -- 默认忽略 NaN 值
cummax_series = s.cummax()
print(cummax_series)
运行结果:
0 2
1 2
2 3
3 5
4 5
5 6
dtype: int64
(10)cummin
该方法用于计算 Series 中元素的累积最小值
返回一个相同长度的Series,其中每个位置上的值表示从Series开始到当前位置(包括当前位置)的最小值。
Series.cummin(axis=None, skipna=True, *args, **kwargs)
axis: 对于Series来说,这个参数不起作用,因为Series是一维的。在DataFrame上使用时,axis=0(默认)表示按列计算,axis=1表示按行计算。
skipna: 布尔值,默认为True。如果为True,则在计算累积最小值时会忽略NaN值;如果为False,则任何NaN值都会传播,并且会导致结果在该位置及之后的值都为NaN。
*args,**kwargs: 这些参数用于兼容性,通常不需要使用。
import pandas as pd
# 创建一个Series
s = pd.Series([2, 1, 3, 5, 4, 6])
# 计算累积最小值 -- 默认忽略 NaN 值
cummin_series = s.cummin()
print(cummin_series)
运行结果:
0 2
1 1
2 1
3 1
4 1
5 1
dtype: int64
(11)cumsum
用于计算 Series 中元素的累积和
该方法返回一个相同长度的Series,其中每个位置上的值表示从Series开始到当前位置(包括当前位置)的所有元素的累加和。
Series.cumsum(axis=None, skipna=True, *args, **kwargs)
axis: 对于Series来说,这个参数不起作用,因为Series是一维的。在DataFrame上使用时,axis=0(默认)表示按列计算,axis=1表示按行计算。
skipna: 布尔值,默认为True。如果为True,则在计算累积和时会忽略NaN值;如果为False,则任何NaN值都会传播,并且会导致结果在该位置及之后的值都为NaN。
*args,**kwargs: 这些参数用于兼容性,通常不需要使用。
import pandas as pd
import numpy as np
# 创建一个Series
s = pd.Series([1, 2, np.nan, 4, 5])
# 计算累积和 -- 默认忽略 NaN 值
cumsum_series = s.cumsum()
print(cumsum_series)
运行结果:
0 1.0
1 3.0
2 NaN
3 7.0
4 12.0
dtype: float64
(12)cumprod
用于计算 Series 中元素的累积乘积
该方法返回一个相同长度的Series,其中每个位置上的值表示从Series开始到当前位置(包括当前位置)的所有元素的累积乘积。
Series.cumprod(axis=None, skipna=True, *args, **kwargs)
axis: 对于Series来说,这个参数不起作用,因为Series是一维的。在DataFrame上使用时,axis=0(默认)表示按列计算,axis=1表示按行计算。
skipna: 布尔值,默认为True。如果为True,则在计算累积乘积时会忽略NaN值;如果为False,则任何NaN值都会导致结果在该位置及之后的值都为NaN。
*args,**kwargs: 这些参数用于兼容性,通常不需要使用。
import pandas as pd
import numpy as np
# 创建一个Series
s = pd.Series([1, 2, np.nan, 4, 5])
# 计算累积乘积 -- 默认忽略 NaN 值
cumprod_series = s.cumprod()
print(cumprod_series)
6. 分组和聚合
(1)groupby
用于将 Series 中的数据分组,并允许你对这些分组进行操作,比如计算每个组的总和、平均值、最大值、最小值等。
Series.groupby(by=None, axis=0, level=None, as_index=True, sort=True, group_keys=True, observed=False, dropna=True)
by:确定分组依据,如果by是一个函数,它会在对象索引的每个值上调用。如果传递了字典或Series,将使用这些对象的值来确定组。如果传递了长度等于所选轴的列表或ndarray,则直接使用这些值来确定组。
axis:用于分组的轴。对于Series,这个参数通常设置为0(默认值),因为Series是一维数据结构。
level:如果索引是多级索引(MultiIndex),则此参数用于指定分组所依据的级别,by和level同时只能存在一个,且必须存在一个。
as_index:是否将分组键作为结果的索引,默认值为True。仅与DataFrame输入相关。
sort:是否对结果进行排序。默认值为True。
group_keys:是否在结果中包含分组键。默认值为True。
observed:是否仅包含实际观察到的分类值。默认值为False。
dropna:是否从结果中排除包含NaN的组。默认值为True。
使用原始 series 对象的值分组:
import pandas as pd
# 创建一个Series对象
data = [10, 20, 10, 30, 20, 10]
series = pd.Series(data)
# 根据Series的值进行分组
grouped = series.groupby(series)
print(grouped) # 会返回一个对象
print(list(grouped)) # 返回具体的分组情况,有几个分组就有几个数组
# 计算每组的计数
grouped = series.groupby(series).count()
print(grouped) # 返回每个分组的计数情况
运行结果:
[(10, 0 10
2 10
5 10
dtype: int64), (20, 1 20
4 20
dtype: int64), (30, 3 30
dtype: int64)]
10 3
20 2
30 1
dtype: int64
使用 series 对象的索引进行分组:
import pandas as pd
# 创建一个Series对象
data = [10, 20, 30, 40, 50, 60]
index = ['a', 'b', 'a', 'b', 'c', 'c']
series = pd.Series(data, index=index)
# 根据Series的索引进行分组
grouped = series.groupby(series.index)
print(grouped)
print(list(grouped))
# 计算每组的和
grouped = series.groupby(series.index).sum()
print(grouped)
运行结果:
[('a', a 10
a 30
dtype: int64), ('b', b 20
b 40
dtype: int64), ('c', c 50
c 60
dtype: int64)]
a 40
b 60
c 110
dtype: int64
使用 series 的多层索引进行分组(不能同时指定level和by,会报错):
import pandas as pd
import numpy as np
arrays = [np.array(['qux', 'qux', 'foo', 'foo', 'baz', 'baz', 'bar', 'bar']),
np.array(['two', 'one', 'two', 'one', 'two', 'one', 'two', 'one'])]
s = pd.Series([1, 2, 3, 4, 5, 6, 7, 8], index=arrays)
print(s)
# 按照arrays[0]分组
res = s.groupby(level=0)
print(res)
print(list(res))
# 按照arrays[0]分组,并求每个分组的平均值
res = s.groupby(level=1).mean()
print(res)
运行结果:
qux two 1
one 2
foo two 3
one 4
baz two 5
one 6
bar two 7
one 8
dtype: int64
[('bar', bar two 7
one 8
dtype: int64), ('baz', baz two 5
one 6
dtype: int64), ('foo', foo two 3
one 4
dtype: int64), ('qux', qux two 1
one 2
dtype: int64)]
one 5.0
two 4.0
dtype: float64
(2)agg
Series.agg()方法用于对 Series 中的数据进行聚合操作
Series.agg(func=None, axis=0, *args, **kwargs)
func: 聚合函数或函数列表/字典。可以是一个函数名称(字符串),也可以是实际的函数对象,或者是这些的列表或字典。如果是字典,则键将是输出列的名称,值应该是应用于Series的函数。
axis: 整数或字符串,默认为0。由于Series是一维数据结构,这个参数实际上在Series的上下文中不起作用。在DataFrame的上下文中,axis=0表示按列进行聚合,axis=1表示按行进行聚合。
*args: 位置参数,可以传递给func。
**kwargs: 关键字参数,可以传递给func。
import pandas as pd
s = pd.Series([1, 2, 3, 4, 5])
# 计算平均值
print("平均值:")
result = s.agg('mean')
print(result)
# 计算最大值和最小值
print("\n最大值、最小值:")
result = s.agg(['max', 'min'])
print(result)
# 使用字典为聚合函数命名
# 键:自定义的输出标签名;值:聚合函数
# 结果是一个 Series,索引为 'Maximum'、'Minimum',值为对应聚合结果
print("\n使用字典为聚合函数命名:")
result = s.agg({'Maximum': 'max', 'Minimum': 'min'})
print(result)
# 使用自定义函数并传递额外的参数
def custom_agg(x, power):
return (x ** power).sum()
def custom_agg2(y,power2):
return (y + power2).mean()
print("\n自定义聚合函数1 一个函数:")
result = s.agg(custom_agg, power=2)
print(result)
print("\n自定义聚合函数2 多个函数:")
result = s.agg([lambda x: custom_agg(x, power=2),
lambda y: custom_agg2(y, power2=5)])
print(result)
print("\n自定义聚合函数3 多个函数并自定义索引名称:")
result = s.agg({
'custom_agg': lambda x: custom_agg(x, power=2),
'custom_agg2': lambda y: custom_agg2(y, power2=5),
})
print(result)
运行结果:
平均值:
3.0
最大值、最小值:
max 5
min 1
dtype: int64
使用字典为聚合函数命名:
Maximum 5
Minimum 1
dtype: int64
自定义聚合函数1 一个函数:
55
自定义聚合函数2 多个函数:
55.0
8.0
dtype: float64
自定义聚合函数3 多个函数并自定义索引名称:
custom_agg 55.0
custom_agg2 8.0
dtype: float64
7. 数据可视化
(1)plot
Series.plot 方法是用来绘制 Series 数据的可视化图表的,该方法提供了灵活的接口,允许用户通过不同的参数来定制图表的类型、样式、布局等,其用法与Matplotlib中的plot相同。
Series.plot(*args, **kwargs)
主要参数:
kind: 图表类型,可以是以下之一:
'line': 折线图(默认)'bar': 柱状图'barh': 水平柱状图'hist': 直方图'box': 箱线图'kde': 核密度估计图'area': 面积图'pie': 饼图'scatter': 散点图'hexbin': 六边形箱图
ax: Matplotlib 轴对象,用于在指定的轴上绘制图表。如果不提供,则创建新的轴对象。
figsize: 图表的尺寸,格式为(width, height),单位为英寸。
use_index: 是否使用 Series 的索引作为 x 轴标签。默认为True。
title: 图表的标题。
grid: 是否显示网格线。默认为False。
legend: 是否显示图例。默认为False。
xticks: x 轴的刻度位置。
yticks: y 轴的刻度位置。
xlim: x 轴的范围,格式为(min, max)。
ylim: y 轴的范围,格式为(min, max)。
color: 绘制颜色,可以是单个颜色或颜色列表。
label: 图例标签。
import pandas as pd
import matplotlib.pyplot as plt
s = pd.Series([1, 3, 2, 4, 5], index=['a', 'b', 'c', 'd', 'e'])
s.plot(kind='line', # 折线
title='Line Plot', # 标题
grid=True, # 显示网格线
figsize=(8, 4), # 画板大小
style='r--', # 颜色+虚线
linewidth=2, # 线宽
label='test', # 图例标签
legend=True, # 显示图例
)
plt.show()

(2)hist
用于绘制 Series 数据直方图的方法。这个方法提供了多种参数来定制直方图的外观和样式。
Series.hist(by=None, ax=None, grid=True, xlabelsize=None, xrot=None, ylabelsize=None, yrot=None, figsize=None, bins=10, backend=None, legend=False, **kwargs)
by:如果不是None,则将数据分组并分别绘制每个组的直方图。
ax: matplotlib的Axes对象,如果指定了,则直方图将绘制在该Axes上。
grid: 布尔值,默认为True,表示是否在直方图上显示网格线。
xlabelsize: int或str,用于设置x轴标签的字体大小。
xrot: int或float,用于设置x轴标签的旋转角度。
ylabelsize: int或str,用于设置y轴标签的字体大小。
yrot: int或float,用于设置y轴标签的旋转角度。
figsize: 元组,用于设置直方图的大小,格式为(width, height)。
bins: int或序列,用于设置直方图的柱子数量或具体的边界。
backend: 用于指定绘图后端,通常 Pandas 会使用 matplotlib。
legend: 布尔值,默认为False,表示是否在直方图上显示图例。
**kwargs: 其他关键字参数,将被传递给 matplotlib 的hist函数。
import pandas as pd
import numpy as np
from matplotlib import pyplot as plt
# 创建一个包含随机数据的Series
s = pd.Series(np.random.randn(1000))
# 绘制直方图 -- 默认不分组(by=None)
s.hist(bins=30, # 设置直方图的柱子数量或具体的边界(int或序列)
figsize=(8, 6), # 直方图的大小
color='blue', # 柱子填充颜色
edgecolor='black' # 柱子边缘颜色
)
# 设置标题和轴标签
plt.title('Histogram of a Random Sample')
plt.xlabel('Value')
plt.ylabel('Frequency')
# 显示图表
plt.show()

8. 其他常用方法
(1)unique
该函数用于返回 Series 中的唯一值。这个方法返回一个数组,其中包含了Series中所有唯一的值。数组中的值是按照它们在原始Series中首次出现的顺序排列的。
Series.unique()
import pandas as pd
# 创建一个Series
s = pd.Series(['apple', 'banana', 'apple', 'orange', 'banana', 'banana'])
# 获取唯一值
unique_values = s.unique()
# 输出唯一值
print(unique_values)
print(type(unique_values))
运行结果:
['apple', 'banana', 'orange']
Length: 3, dtype: str
(2)nunique
该函数用于计算Series中唯一值的数量。这个方法返回一个整数,表示Series中唯一值的数量。
Series.nunique(dropna=True)
dropna:布尔值,默认为True。如果为True,则在计算唯一值数量之前,会先从Series中排除NaN值
import pandas as pd
# 创建一个Series
s = pd.Series(['apple', 'banana', 'apple', 'orange', 'banana', 'banana'])
# 计算唯一值的数量(排除NaN)
unique_count = s.nunique(dropna=True)
# 输出唯一值的数量
print(unique_count)
(3)value_counts
该方法用于计算Series中每个值的出现次数。这个方法返回一个包含每个唯一值及其对应出现次数的Series。
Series.value_counts(normalize=False, sort=True, ascending=False, bins=None, dropna=True)
normalize:布尔值(True/False)
默认为False,返回计数;如果为True,返回相对频率,相对频率基于参与计数(未被 dropna 排除)的值的总数sort:布尔值,是否按频率排序
默认为True,结果按计数值(频率)降序排序
若为False, 则不按频率排序,保留数据在原始 Series 中首次出现的顺序ascending:布尔值,只在sort=True时才有意义,判断升序还是降序
默认为False,结果按计数值降序排序;为True,结果按计数值升序排序bins:用于离散化连续数据,可以是整数或分位数数组。如果指定了bins,则结果将是每个bin(箱子) 的计数dropna:布尔值,默认为True,排除 NaN 值
import pandas as pd
import numpy as np
# 创建一个Series
s = pd.Series(['apple', 'banana', 'apple', 'orange', np.nan, 'banana', 'banana'])
# 返回相对频率
value_frequency = s.value_counts(normalize=True)
print(f"参与计数的值:\n{value_frequency}")
value_frequency = s.value_counts(normalize=True, dropna=False)
print(f"\n所有值,包括nan:\n{value_frequency}")
# 计算每个值的出现次数 -- 默认:sort=true(要排序),ascending=false(降序)
value_counts = s.value_counts()
# 输出每个值的出现次数
print(f"\n按照频率降序排序:\n{value_counts}")
# 计算每个值的出现次数 -- 修改:sort=true(要排序),ascending=true(升序)
value_counts = s.value_counts(ascending=True)
# 输出每个值的出现次数
print(f"\n按照频率升序排序:\n{value_counts}")
# 计算每个值的出现次数 -- 修改:sort=false(不排序)
value_counts = s.value_counts(sort=False)
# 输出每个值的出现次数
print(f"\n不按照频率排序,按照首次出现的顺序输出:\n{value_counts}")
# 离散化连续数据 -- 只能用于数值类型的数据,字符串不行
s = pd.Series([12, 15, 18, 20, 25, 28, 30, 35, 40, 45])
value_discrete = s.value_counts(bins=5) # 分5组,每个区间差为(45-12)/5=6.6
print(f"\n离散化连续数据:\n{value_discrete}")
运行结果:
参与计数的值:
banana 0.500000
apple 0.333333
orange 0.166667
Name: proportion, dtype: float64
所有值,包括nan:
banana 0.428571
apple 0.285714
orange 0.142857
NaN 0.142857
Name: proportion, dtype: float64
按照频率降序排序:
banana 3
apple 2
orange 1
Name: count, dtype: int64
按照频率升序排序:
orange 1
apple 2
banana 3
Name: count, dtype: int64
不按照频率排序,按照首次出现的顺序输出:
apple 2
banana 3
orange 1
Name: count, dtype: int64
离散化连续数据:
(11.966000000000001, 18.6] 3
(18.6, 25.2] 2
(25.2, 31.8] 2
(38.4, 45.0] 2
(31.8, 38.4] 1
Name: count, dtype: int64
(4)describe
该方法用于生成描述性统计信息。这个方法返回一个包含计数、均值、标准差、最小值、25%分位数、中位数、75%分位数和最大值的 Series。
Series.describe(percentiles=None, include=None, exclude=None)
percentiles:数值列表或数值元组,默认为[.25, .5, .75],表示要包含在输出中的分位数。include:字符串或类型列表,用于指定要包括在结果中的数据类型。默认为None,即包括所有数字类型。exclude:字符串或类型列表,用于指定要从结果中排除的数据类型。默认为None。
import pandas as pd
# 创建一个Series
s = pd.Series([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
# 生成描述性统计信息
description = s.describe()
# 输出描述性统计信息
print(description)
运行结果:
count 10.00000
mean 5.50000
std 3.02765
min 1.00000
25% 3.25000
50% 5.50000
75% 7.75000
max 10.00000
dtype: float64
(5)copy
该函数用于创建Series对象的一个副本。
Series.copy(deep=True)
deep:布尔值,默认为True。
当deep=True时,会进行深拷贝,即复制数据和索引的副本,而不是仅仅复制引用
当deep=False时,会进行浅拷贝,即只复制数据或索引的引用。
import pandas as pd
# 创建一个Series
original_series = pd.Series([1, 2, 3, 4, 5])
# 创建一个深拷贝 -- 复制底层数据,修改副本不会影响原数据
deep_copied_series = original_series.copy()
# 创建一个浅拷贝 -- 不立即复制底层数据
# Pandas 3.0 及以上默认采用写时复制,修改副本不会影响原数据
# Pandas 3.0 以下未启用写时复制时,修改一方通常会影响另一方
shallow_copied_series = original_series.copy(deep=False)
# 修改深拷贝中的数据
deep_copied_series[0] = 999
# 输出原始Series和深拷贝后的Series
print(f"Original Series:\n{original_series}")
print(f"Deep Copied Series:\n{deep_copied_series}")
# 修改浅拷贝中的数据
shallow_copied_series[1] = 888
# 输出原始Series和浅拷贝后的Series -- 不会修改原数据
print(f"Original Series after shallow_copied_series):\n{original_series}")
print(f"Shallow Copied Series:\n{shallow_copied_series}")
(6)reset_index
该函数用于重置Series的索引,将原来的索引转换为一个列,并将一个新的默认整数索引赋给Series。
Series.reset_index(level=None, *, drop=False, name=no_default, inplace=False, allow_duplicates=False)
level:int 或 level 名,可选
如果 Series 是多级索引 (MultiIndex),则只移除指定的级别
默认为None,移除所有级别drop:布尔值,默认为False
如果为True,则不将旧索引添加为新列,直接丢弃name:字符串,可选
用于新列的名称,默认为no_default
如果未指定,并且索引有名字,则使用索引的名字inplace:布尔值,默认为False
如果为True,则在原地修改 Series,不返回新的对象
该参数自3.1.0版本起已废弃:该关键字已被弃用,将在pandas 4.0中彻底移除allow_duplicates:布尔值,默认为False
如果为True,则允许在重置索引后出现重复的索引值
默认情况下,如果出现重复的索引值,Pandas 会抛出错误,对 Series 无用
import pandas as pd
import numpy as np
# 创建一个简单的Series对象
data = pd.Series(np.random.randint(1, 100, 5), index=['c', 'a', 'e', 'b', 'd'])
print("排序前:")
print(data)
# 对Series进行排序 -- 按照值排序
sorted_series = data.sort_values()
print("\n排序后的Series: ")
print(sorted_series)
# 重置索引
reset_indexed_series = sorted_series.reset_index()
print("\n重置索引后的Series: ")
print(reset_indexed_series)
reset_indexed_series = sorted_series.reset_index(drop=True)
print("\n重置索引后的Series -- 丢弃旧索引: ")
print(reset_indexed_series)
reset_indexed_series = sorted_series.reset_index(name='new')
print("\n重置索引后的Series -- 指定新列的名称: ")
print(reset_indexed_series)
# 验证 allow_duplicates=True:允许新生成的列名与现有列名重复
s = pd.Series([10, 20, 30], index=pd.Index(['a', 'b', 'c'], name='index'))
s.name = 'index'
print(f"\n原始 Series:\n{s}")
print("\n允许重复列名:")
print(s.reset_index(allow_duplicates=True))
print("\n不允许重复列名:抛出 ValueError")
# print(s.reset_index(allow_duplicates=False)) # 由于新生成的索引列与原数据列名称冲突,会抛出 ValueError
运行结果:
排序前:
c 16
a 51
e 77
b 18
d 36
dtype: int32
排序后的Series:
c 16
b 18
d 36
a 51
e 77
dtype: int32
重置索引后的Series:
index 0
0 c 16
1 b 18
2 d 36
3 a 51
4 e 77
重置索引后的Series -- 丢弃旧索引:
0 16
1 18
2 36
3 51
4 77
dtype: int32
重置索引后的Series -- 指定新列的名称:
index new
0 c 16
1 b 18
2 d 36
3 a 51
4 e 77
原始 Series:
index
a 10
b 20
c 30
Name: index, dtype: int64
允许重复列名:
index index
0 a 10
1 b 20
2 c 30
不允许重复列名:抛出 ValueError
(7)info
用于显示Series的概要信息的方法。这个方法提供了关于Series的元数据,包括数据类型、非空值的数量、内存使用情况等。
Series.info(verbose=None, buf=None, max_cols=None, memory_usage=None, show_counts=True)
verbose:布尔值或None,默认为None。如果为True,则输出更详细的信息。buf:一个文件-like对象,如果提供,则将输出写入这个对象而不是标准输出。max_cols:int,用于显示的最大列数。如果列数超过这个值,则显示“...”。memory_usage:布尔值或str,默认为None。如果为True,则显示内存使用情况。如果设置为deep,则会计算列的内存使用情况,这可能非常慢。show_counts:布尔值,默认为True。如果为True,则显示非空值的数量。
import numpy as np
import pandas as pd
# 创建一个示例Series
s = pd.Series([1, 2, np.nan, 4, 5], name='example_series', index=['a', 'b', 'c', 'd', 'e'])
# 显示Series的概要信息
s.info()
运行结果:
Index: 5 entries, a to e
Series name: example_series
Non-Null Count Dtype
-------------- -----
4 non-null float64
dtypes: float64(1)
memory usage: 80.0+ bytes
(8)apply
对 Series 中的每个元素应用一个函数,并返回一个结果 Series。
Series.apply(func, convert_dtype=True, args=(), **kwargs)
func:一个函数,它将被应用到Series的每一个元素上。这个函数可以是Python的内置函数,也可以是用户自定义的函数。convert_dtype:布尔值,默认为True。如果为True,则在可能的情况下,Pandas 会尝试将结果转换为适合的数据类型。args:一个元组,包含传递给func的位置参数。**kwargs:一个字典,包含传递给func的关键字参数。
import pandas as pd
# 创建一个series
series = pd.Series([1, 2, 3, 4, 5])
# 使用apply方法结合lambda函数,对series中的每个元素执行平方操作
res = series.apply(lambda x: x * 2)
# 打印结果,输出每个元素的平方值
print(res)
(9)map
对series中的每个元素应用一个映射,它允许你将一个函数应用到series的每个元素上,或者将一个字典或series映射到series的值上。
Series.map(arg, na_action=None)
arg:这可以是以下几种类型:- 函数:将此函数应用于series的每个元素。
- 字典:将series中的值映射到字典的键上,返回对应的值。
- Series:使用另一个series的索引来映射当前series的值。
na_action:默认为None。如果设置为'ignore',并且arg是一个函数,那么将忽略 NaN 值,并保留它们不变。
将一个函数应用到series的每个元素上:
import pandas as pd
# 创建一个series
s = pd.Series([1, 2, 3, 4, 5])
# 定义一个函数,用于将值翻倍
def double(x):
return x * 2
# 使用map方法应用这个函数
s_doubled = s.map(double)
print(s_doubled)
将一个字典应用到 series 的每个元素上:
import pandas as pd
# 创建一个映射字典
grade_mapping = {
90: 'A',
80: 'B',
70: 'C',
60: 'D',
0: 'F'
}
# 创建一个成绩的Series
grades = pd.Series([80, 92, 77, 60, 100])
# 使用map方法应用这个字典
grades_mapped = grades.map(grade_mapping)
print(grades_mapped)
将一个 Series 对象应用到 series 的每个元素上:
import pandas as pd
# 创建一个名为series1的Series对象
series1 = pd.Series([50, 60, 70, 80, 90], index=['a', 'b', 'c', 'd', 'e'])
# 创建一个名为grades的Series对象,代表成绩数据
grades = pd.Series([80, 92, 'c', 59, 100], index=[0, 1, 2, 3, 4])
# 使用grades的map方法,会把 grades 中的每个值当作 series1 的索引标签(键)进行查找,而不是当作 series1 中的数据值进行查找
res = grades.map(series1)
# 打印输出新生成的Series对象res
print(res)
运行结果:
0 NaN
1 NaN
2 70.0
3 NaN
4 NaN
dtype: float64
(三)二维数组 DataFrame
二维数组则是可以理解为excel表格:

1. DataFrame的创建
在 Pandas 中,使用 DataFrame 来创建二维数组 DataFrame:
class pandas.DataFrame(data=None, index=None, columns=None, dtype=None,copy=None)
data:数据源,可以是以下几种形式:- 列表,其中每个元素是一行数据
- 字典,其中键是列名,值是列值(列表或数组)
- 2d-Ndarray
Series对象,每个Series成为一列。
index:行标签,如果没有指定,默认是整数索引[0, ..., n-1],其中 n 是数据中的行数columns:列标签,如果没有指定,则列标签从数据源中推断dtype:指定某列的数据类型。如果指定,则所有列都将转换为指定的数据类型copy:布尔值,默认为None。如果为True,则复制数据;如果为False,则尽可能避免复制数据
(1)使用列表创建
初始列表:
import pandas as pd
# 创建一个包含学生信息的列表,每个元素代表一个学生的姓名
data_list = ['小明', '小红', '小刚']
#定义列名
columns = ['姓名']
#使用 pandas 库创建一个 DataFrame,将数据列表和列名作为参数传入
df = pd.DataFrame(data_list, columns=columns)
#打印 DataFrame 以查看数据
print(df)
运行结果:
姓名
0 小明
1 小红
2 小刚
嵌套列表:
import pandas as pd
# 创建一个包含学生信息的嵌套列表,每个子列表代表一个学生的姓名、年龄和成绩
data_list = [
['小明', 20, 85],
['小红', 18, 90],
['小刚', 22, 88]
]
# 定义列名,分别对应姓名、年龄和成绩
columns = ['姓名', '年龄', '成绩']
# 使用 pandas 库创建一个 DataFrame,将数据列表和列名作为参数传入
df = pd.DataFrame(data_list, columns=columns)
# 打印 DataFrame 以查看数据
print(df)
运行结果:
姓名 年龄 成绩
0 小明 20 85
1 小红 18 90
2 小刚 22 88
(2)使用字典创建
可以使用一个字典来创建 DataFrame
其中字典的键将作为列名,字典的值可以是列表、数组等可迭代对象
它们的长度要一致,代表每一列的数据。
字典中指定了列名,就不要单独指定列标签
import pandas as pd
# 定义一个字典,其中包含两组数据:姓名和年龄
data = {
'Name': ['Tom', 'Nick', 'John'], # 'Name' 键对应一个包含姓名的列
'Age': [20, 21, 19] # 'Age' 键对应一个包含年龄的列
}
# 使用 pd.DataFrame() 函数将字典转换为 DataFrame 对象
# data 字典中的键自动成为 DataFrame 的列名,值成为列的数据
df = pd.DataFrame(data)
# 打印 DataFrame 对象,查看其内容
print(df)
运行结果:
Name Age
0 Tom 20
1 Nick 21
2 John 19
(3)使用Ndarray数组创建
import pandas as pd
import numpy as np
# 定义一个二维 Ndarray 数组,其中包含两组数据:姓名和年龄
data_array = np.array([
['Tom', 20],
['Nick', 21],
['John', 19]
])
# 使用 pd.DataFrame() 函数将二维数组转换为 DataFrame 对象
df = pd.DataFrame(data_array, columns=['Name', 'Age'])
# 打印
print(df)
运行结果:
Name Age
0 Tom 20
1 Nick 21
2 John 19
(4)使用Series创建
如果有多个 Series 对象,也可以将它们组合成一个 DataFrame
import pandas as pd
# 创建三个 pandas Series 对象
s1 = pd.Series(['小明', '小红', '小刚'], name='姓名')
s2 = pd.Series([20, 18, 22, 0], name='年龄')
s3 = pd.Series([85, 90, 88], name='成绩')
# 将 Series 对象组合成一个字典,键是 series 的名称,值是 Series 本身
# 然后将这个字典传递给 DataFrame 构造函数来创建一个 DataFrame
df = pd.DataFrame({s1.name: s1, s2.name: s2, s3.name: s3})
# 打印 DataFrame 对象,查看其内容
print(df)
运行结果:
姓名 年龄 成绩
0 小明 20 85.0
1 小红 18 90.0
2 小刚 22 88.0
3 NaN 0 NaN
import pandas as pd
# 创建三个 pandas Series 对象
s1 = pd.Series(['小明', '小红', '小刚'], name='姓名')
s2 = pd.Series([20, 18, 22, 0], name='年龄')
s3 = pd.Series([85, 90, 88], name='成绩')
# 使用 concat 拼接,并指定轴为 1
df = pd.concat([s1, s2, s3], axis=1)
# 打印 DataFrame 对象,查看其内容
print(df)
运行结果:
姓名 年龄 成绩
0 小明 20 85.0
1 小红 18 90.0
2 小刚 22 88.0
3 NaN 0 NaN
2. DataFrame的属性
(1)index
返回 DataFrame 的行索引
import pandas as pd
# 定义字典数据,包含姓名、年龄和成绩三个字段
data = {
'姓名': ['小明', '小红', '小刚'],
'年龄': [20, 18, 22],
'成绩': [85, 90, 88]
}
# 将字典转换为 DataFrame,并自定义行索引为 'a', 'b', 'c'
df = pd.DataFrame(data, index=['a', 'b', 'c'])
# 打印输出的 DataFrame 数据
print(df)
# ========== 1. 返回 DataFrame 的行索引 ==========
print("\n行索引 -- \n",df.index)
(2)columns
返回 DataFrame 的列名
import pandas as pd
# 定义字典数据,包含姓名、年龄和成绩三个字段
data = {
'姓名': ['小明', '小红', '小刚'],
'年龄': [20, 18, 22],
'成绩': [85, 90, 88]
}
# 将字典转换为 DataFrame,并自定义行索引为 'a', 'b', 'c'
df = pd.DataFrame(data, index=['a', 'b', 'c'])
# 打印输出的 DataFrame 数据
print(df)
# ========== 2. 返回 DataFrame 的列名 ==========
print("\n列名 -- \n",df.columns)
(3)values
返回 DataFrame 中数据的 Ndarray 表示
import pandas as pd
# 定义字典数据,包含姓名、年龄和成绩三个字段
data = {
'姓名': ['小明', '小红', '小刚'],
'年龄': [20, 18, 22],
'成绩': [85, 90, 88]
}
# 将字典转换为 DataFrame,并自定义行索引为 'a', 'b', 'c'
df = pd.DataFrame(data, index=['a', 'b', 'c'])
# 打印输出的 DataFrame 数据
print(df)
# ========== 3. 返回 DataFrame 中数据的 Ndarray 表示 ==========
print("\nNdarray(矩阵)表示 -- \n",df.values)
(4)dtypes
返回每列的数据类型,没有 dtype 属性
import pandas as pd
# 定义字典数据,包含姓名、年龄和成绩三个字段
data = {
'姓名': ['小明', '小红', '小刚'],
'年龄': [20, 18, 22],
'成绩': [85, 90, 88]
}
# 将字典转换为 DataFrame,并自定义行索引为 'a', 'b', 'c'
df = pd.DataFrame(data, index=['a', 'b', 'c'])
# 打印输出的 DataFrame 数据
print(df)
# ========== 4. 返回每列的数据类型 ==========
print("\n每列的数据类型 -- \n",df.dtypes)
(5)shape
返回 DataFrame 的形状(行数,列数)
import pandas as pd
# 定义字典数据,包含姓名、年龄和成绩三个字段
data = {
'姓名': ['小明', '小红', '小刚'],
'年龄': [20, 18, 22],
'成绩': [85, 90, 88]
}
# 将字典转换为 DataFrame,并自定义行索引为 'a', 'b', 'c'
df = pd.DataFrame(data, index=['a', 'b', 'c'])
# 打印输出的 DataFrame 数据
print(df)
# ========== 5. 返回 DataFrame 的形状(行数,列数) ==========
print("\n形状(行数,列数) -- \n",df.shape)
(6)size
返回 DataFrame 中的元素数量
import pandas as pd
# 定义字典数据,包含姓名、年龄和成绩三个字段
data = {
'姓名': ['小明', '小红', '小刚'],
'年龄': [20, 18, 22],
'成绩': [85, 90, 88]
}
# 将字典转换为 DataFrame,并自定义行索引为 'a', 'b', 'c'
df = pd.DataFrame(data, index=['a', 'b', 'c'])
# 打印输出的 DataFrame 数据
print(df)
# ========== 6. 返回 DataFrame 中的元素数量 ==========
print("\n元素数量 -- \n",df.size)
(7)empty
返回 DataFrame 是否为空
import pandas as pd
# 定义字典数据,包含姓名、年龄和成绩三个字段
data = {
'姓名': ['小明', '小红', '小刚'],
'年龄': [20, 18, 22],
'成绩': [85, 90, 88]
}
# 将字典转换为 DataFrame,并自定义行索引为 'a', 'b', 'c'
df = pd.DataFrame(data, index=['a', 'b', 'c'])
# 打印输出的 DataFrame 数据
print(df)
# ========== 7. 返回 DataFrame 是否为空 ==========
print("\n是否为空 -- \n",df.empty)
(8)T
返回 DataFrame 的转置
import pandas as pd
# 定义字典数据,包含姓名、年龄和成绩三个字段
data = {
'姓名': ['小明', '小红', '小刚'],
'年龄': [20, 18, 22],
'成绩': [85, 90, 88]
}
# 将字典转换为 DataFrame,并自定义行索引为 'a', 'b', 'c'
df = pd.DataFrame(data, index=['a', 'b', 'c'])
# 打印输出的 DataFrame 数据
print(df)
# ========== 8. 返回 DataFrame 的转置 ==========
res = df.T
print("\n转置 -- \n",res)
(9)axes
返回行轴和列轴的列表
import pandas as pd
# 定义字典数据,包含姓名、年龄和成绩三个字段
data = {
'姓名': ['小明', '小红', '小刚'],
'年龄': [20, 18, 22],
'成绩': [85, 90, 88]
}
# 将字典转换为 DataFrame,并自定义行索引为 'a', 'b', 'c'
df = pd.DataFrame(data, index=['a', 'b', 'c'])
# 打印输出的 DataFrame 数据
print(df)
# ========== 9. 返回行轴和列轴的列表 ==========
print("\n行轴和列轴的列表 -- \n",df.axes)
print("\n存储的元数据 -- \n",df.attrs)
(10)ndim
返回 DataFrame 的维度数。对于标准的二维 DataFrame,这个值通常是 2
import pandas as pd
# 定义字典数据,包含姓名、年龄和成绩三个字段
data = {
'姓名': ['小明', '小红', '小刚'],
'年龄': [20, 18, 22],
'成绩': [85, 90, 88]
}
# 将字典转换为 DataFrame,并自定义行索引为 'a', 'b', 'c'
df = pd.DataFrame(data, index=['a', 'b', 'c'])
# 打印输出的 DataFrame 数据
print(df)
# ========== 10. 返回 DataFrame 的维度数 ==========
print("\n维度数 -- \n",df.ndim)
(11)attrs
允许用户存储DataFrame的元数据,它是一个字典,可以用来存储任意与DataFrame相关的额外信息
import pandas as pd
# 定义字典数据,包含姓名、年龄和成绩三个字段
data = {
'姓名': ['小明', '小红', '小刚'],
'年龄': [20, 18, 22],
'成绩': [85, 90, 88]
}
# 将字典转换为 DataFrame,并自定义行索引为 'a', 'b', 'c'
df = pd.DataFrame(data, index=['a', 'b', 'c'])
# 打印输出的 DataFrame 数据
print(df)
# ========== 11. 允许用户存储DataFrame的元数据 ==========
# 是一个字典,可以用来存储任意与DataFrame相关的额外信息
df.attrs['creator'] = 'clover'
df.attrs['created_at'] = '2026-10-26'
print("\n存储的元数据 -- \n",df.attrs)
(12)运行结果
姓名 年龄 成绩
a 小明 20 85
b 小红 18 90
c 小刚 22 88
行索引 --
Index(['a', 'b', 'c'], dtype='str')
列名 --
Index(['姓名', '年龄', '成绩'], dtype='str')
Ndarray(矩阵)表示 --
[['小明' 20 85]
['小红' 18 90]
['小刚' 22 88]]
每列的数据类型 --
姓名 str
年龄 int64
成绩 int64
dtype: object
形状(行数,列数) --
(3, 3)
元素数量 --
9
是否为空 --
False
转置 --
a b c
姓名 小明 小红 小刚
年龄 20 18 22
成绩 85 90 88
行轴和列轴的列表 --
[Index(['a', 'b', 'c'], dtype='str'), Index(['姓名', '年龄', '成绩'], dtype='str')]
维度数 --
2
存储的元数据 --
{'creator': 'clover', 'created_at': '2026-10-26'}
3. DataFrame中元素的索引与访问
(1)使用列名访问
对于 DataFrame 来说,可以直接使用列名来访问某一列的数据,返回的是一个Series对象
import pandas as pd
data = {
'姓名': ['小明', '小红', '小刚'],
'年龄': [20, 18, 22],
'成绩': [85, 90, 88]
}
df = pd.DataFrame(data)
print("访问完整数据:")
print(df)
print("\n访问列名为'姓名'的列:")
print(df['姓名'])
print("\n访问列名为'姓名'和'年龄'的列:")
print(df[['姓名', '年龄']])
(2)loc和iloc
可以使用 loc 与 iloc 属性访问单个或多个数据,其语法为:
df.loc[row_label, column_label]
loc:根据标签(Label)选择数据iloc:根据整数位置(Integer Location)选择数据
import pandas as pd
data = {
'姓名': ['小明', '小红', '小刚'],
'年龄': [20, 18, 22],
'成绩': [85, 90, 88]
}
df = pd.DataFrame(data)
print("访问完整数据:")
print(df)
print("\n访问【第 1 行,'姓名'列】的数据:")
print(df.loc[0, '姓名'])
print("\n访问【第 0 到 2 行,'姓名'到'成绩'列】的数据:")
print(df.loc[0:2, '姓名':'成绩'])
print("\n访问【第 0 行,第 0 列】的数据:")
print(df.iloc[0, 0])
print("\n访问【第 0 到 1 行,第 0 到 1 列】的数据:")
print(df.iloc[0:1, 0:1])
(3)at和iat
使用 at 和 iat 属性来访问单个数据
at:根据行标签和列标签,访问单个值iat:根据行位置和列位置,访问单个值
import pandas as pd
data = {
'姓名': ['小明', '小红', '小刚'],
'年龄': [20, 18, 22],
'成绩': [85, 90, 88]
}
df = pd.DataFrame(data)
print("访问完整数据:")
print(df)
print("\n访问【第 0 行,'姓名'列】的数据:")
print(df.at[0, '姓名'])
print("\n访问【第 0 行,第 0 列】的数据:")
print(df.iat[0, 0])
(4)head
该方法用于获取 DataFrame 的前 n 行。默认情况下,如果不指定 n 的值,它会返回前 5 行
DataFrame.head(n=5)
n:整数,表示要返回的行数。默认值为5
import pandas as pd
# 创建一个示例 DataFrame
data = {
'A': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
'B': [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
}
df = pd.DataFrame(data)
# 使用 head 方法获取前 5 行
print(df.head())
(5)tail
该方法用于获取 DataFrame 的最后 n 行。与 DataFrame.head 方法类似,如果不指定 n 的值,它会默认返回最后 5 行
DataFrame.tail(n=5)
n:整数,表示要返回的行数。默认值为5
import pandas as pd
# 创建一个示例 DataFrame
data = {
'A': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
'B': [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
}
df = pd.DataFrame(data)
# 使用 tail 方法获取最后5行
print(df.tail())
(6)isin
DataFrame.isin(values) 方法用于检查 DataFrame 中的元素是否包含在指定的集合 values 中。这个方法会返回一个布尔型 DataFrame,其中的每个元素都表示原始DataFrame 中对应元素是否在 values 中
DataFrame.isin(values)
values:可以是单个值、列表、元组、集合或另一个DataFrame / Series。如果values是一个字典,键是列名,值是列表或元组,表示该列中要检查的值
import pandas as pd
# 创建一个示例DataFrame
data = {
'A': [1, 2, 3, 4, 5],
'B': ['a', 'b', 'c', 'd', 'e']
}
df = pd.DataFrame(data)
# 检查 DataFrame 中的元素是否包含在指定的值集合中
values_to_check = [2, 4, 'c']
print(df.isin(values_to_check))
运行结果:
A B
0 False False
1 True False
2 False True
3 True False
4 False False
(7)get
用于从 DataFrame 中获取列,它类似于直接使用 df[key] 来访问列,但是当列不存在时, get 方法提供了一个更安全的方式来处理这种情况,你可以指定一个默认值,而不是引发一个错误
DataFrame.get(key, default=None)
key:你想获取的列的名称default:如果列不存在时返回的默认值。默认是 None 。
import pandas as pd
data = {
'姓名': ['小明', '小红', '小刚'],
'年龄': [20, 18, 22],
'成绩': [85, 90, 88]
}
df = pd.DataFrame(data)
# 获取'成绩'列
scores = df.get('成绩')
# 尝试获取不存在的列,返回指定值
non_existent_column = df.get('体重', default='Not Found')
print(scores)
print(non_existent_column)
4. 数据操作
(1)数据清洗
isnull()
用于检测 DataFrame 中的缺失值,它会返回一个相同形状的布尔型 DataFrame,其中每个元素表示原始 DataFrame 中相应位置的元素是否是缺失值
import pandas as pd
import numpy as np
# 创建一个包含缺失值的 DataFrame
df = pd.DataFrame({
'A': [1, 2, np.nan],
'B': [4, np.nan, 6],
'C': [7, 8, 9]
})
# 打印原始 DataFrame
print(df)
# 使用 isnull() 方法检测缺失值
missing_values = df.isnull()
print(missing_values)
运行结果:
A B C
0 1.0 4.0 7
1 2.0 NaN 8
2 NaN 6.0 9
A B C
0 False False False
1 False True False
2 True False False
dropna()
用于删除 DataFrame 中的缺失值
DataFrame.dropna(axis=0, how=any, thresh=_NoDefault.no_default, subset=None, inplace=False, ignore_index=False)
axis:{0 或 'index', 1 或 'columns'},默认为 0。0表示按行删除,1表示按列删除how:{'any', 'all'},默认为 'any'。确定删除缺失值的逻辑:- 'any':如果行或列中的任意一个值是 NaN,就删除该行或列
- 'all':如果行或列中的所有值都是 NaN,才删除该行或列
thresh:指定每行或每列至少需要有多少个非缺失值才能保留。如果设置此参数,how 参数将被忽略subset:指定在哪些列中搜索缺失值。如果未指定,则在所有列中搜索inplace:是否修改 DataFrame 而不是创建新的 DataFrameignore_index:布尔值,默认为 False。如果为 True,则不保留原始 DataFrame 的索引
import pandas as pd
import numpy as np
# 创建一个包含缺失值的 DataFrame
df = pd.DataFrame({
'A': [1, 2, np.nan],
'B': [4, np.nan, 6],
'C': [7, 8, 9]
})
# 打印原始 DataFrame
print(df)
# 删除任何含有 NaN 值的行
df_cleaned = df.dropna()
print(df_cleaned)
运行结果:
A B C
0 1.0 4.0 7
1 2.0 NaN 8
2 NaN 6.0 9
A B C
0 1.0 4.0 7
fillna()
用于填充 DataFrame 中的缺失值
DataFrame.fillna(value=None, *, method=None, axis=0, inplace=False, limit=None)
value:填充值,可以是单个值,也可以是字典(对不同的列填充不同的值),或者一个 Seriesmethod:{'bfill', 'ffill'},默认为无默认值。指定填充方法:- 'bfill' 或 'backfill':使用下一个有效观测值填充
- 'ffill' 或 'pad':使用前一个有效观测值填充
- pandas 3.1.0 中没有
method了,直接df.bfill()/df.ffill()
axis:{0 或 'index', 1 或 'columns'},默认为 0inplace:布尔值,默认为 False。如果为 True,则在原地修改 DataFrame 而不返回新的 DataFramelimit:int,默认为无默认值。如果指定了method,则该参数限制连续填充的数量
import pandas as pd
import numpy as np
# 创建一个包含缺失值的 DataFrame
df = pd.DataFrame({
'A': [1, 2, np.nan],
'B': [np.nan, np.nan, 6],
'C': [7, np.nan, 9]
})
# 打印原始 DataFrame
print(df)
# 使用固定值填充缺失值
print("\n固定值填充 -- ")
df_filled_value = df.fillna(value=0)
print(df_filled_value)
# 使用字典填充
print("\n字典填充 -- ")
data = {
'A': 'a',
'B': 'b',
'C': 'c'
}
df_filled_dict = df.fillna(value=data)
print(df_filled_dict)
# 使用 Series 填充
print("\nSeries 填充 -- ")
data_series = pd.Series(['a', 'b', 'c'], ['A', 'B', 'C'])
df_filled_series = df.fillna(value=data_series)
print(df_filled_series)
# 使用前一个有效观测值填充缺失值
print("\n前值填充 -- ")
df_filled_ffill = df.ffill()
print(df_filled_ffill)
# 使用后一个有效观测值填充缺失值
print("\n后值填充 -- ")
df_filled_bfill = df.bfill()
print(df_filled_bfill)
运行结果:
A B C
0 1.0 NaN 7.0
1 2.0 NaN NaN
2 NaN 6.0 9.0
固定值填充 --
A B C
0 1.0 0.0 7.0
1 2.0 0.0 0.0
2 0.0 6.0 9.0
字典填充 --
A B C
0 1.0 b 7.0
1 2.0 b c
2 a 6.0 9.0
Series 填充 --
A B C
0 1.0 b 7.0
1 2.0 b c
2 a 6.0 9.0
前值填充 --
A B C
0 1.0 NaN 7.0
1 2.0 NaN 7.0
2 2.0 6.0 9.0
后值填充 --
A B C
0 1.0 6.0 7.0
1 2.0 6.0 9.0
2 NaN 6.0 9.0
drop_duplicates()
用于删除 DataFrame 中的重复行
DataFrame.drop_duplicates(subset=None, keep='first', inplace=False, ignore_index=False)
subset:指定要检查重复的列名或列名列表,默认值为None,表示检查所有列keep:{'first', 'last', False},默认为 'first'。确定如何处理重复项:- 'first':保留第一次出现的重复项
- 'last':保留最后一次出现的重复项
- False:删除所有重复项
inplace:是否修改 DataFrame 而不是创建新的 DataFrameignore_index:是否重置索引值
import pandas as pd
# 创建一个包含重复行的 DataFrame
df = pd.DataFrame({
'A': [1, 1, 2, 2, 3, 3],
'B': [1, 1, 2, 2, 3, 3],
'C': [1, 1, 2, 2, 3, 3]
})
# 打印原始 DataFrame
print(df)
# 删除重复行,保留第一次出现的重复项
print("\n保留第一次出现的重复项 --")
df_dedup_first = df.drop_duplicates()
print(df_dedup_first)
# 根据指定列删除重复行
print("\n指定列删除重复行 --")
df_dedup_column = df.drop_duplicates(subset=['A'])
print(df_dedup_column)
# 删除重复行,保留最后一次出现的重复项
print("\n保留最后一次出现的重复项 --")
df_dedup_last = df.drop_duplicates(keep='last')
print(df_dedup_last)
# 删除所有重复行
print("\n删除所有重复行 --")
df_dedup_all = df.drop_duplicates(keep=False)
print(df_dedup_all)
运行结果:
A B C
0 1 1 1
1 1 1 1
2 2 2 2
3 2 2 2
4 3 3 3
5 3 3 3
保留第一次出现的重复项 --
A B C
0 1 1 1
2 2 2 2
4 3 3 3
指定列删除重复行 --
A B C
0 1 1 1
2 2 2 2
4 3 3 3
保留最后一次出现的重复项 --
A B C
1 1 1 1
3 2 2 2
5 3 3 3
删除所有重复行 --
Empty DataFrame
Columns: [A, B, C]
Index: []
(2)数据转换
replace()
用于替换 DataFrame 中的值
DataFrame.replace(to_replace=None, value=_NoDefault.no_default, inplace=False, limit=None, regex=False, method=_NoDefault.no_default)
to_replace:被替换的内容,可以是 scalar, list, dict, regex。如果是字典,则键是要替换的值,值是相应的替换值。value:替换后的值。可以是单个值、列表或数组,与to_replace长度相同。inplace:是否在原地修改 DataFrame。limit:限制替换的数量。可以是整数,表示最多替换多少个值。regex:是否使用正则表达式进行匹配。默认值为 False。method:替换方法。可以是:- 'pad' 或 'ffill':使用前面的数据向后填充。
- 'backfill' 或 'bfill':使用后面的数据向前填充。
- pandas 3.1.0 中没有
method了,直接df.bfill()/df.ffill()
import pandas as pd
# 创建一个 DataFrame
df = pd.DataFrame({
'A': [1, 2, 3, 4, 5],
'B': ['a', 'b', 'a', 'b', 'a']
})
# 打印原始 DataFrame
print(df)
# 用数字 100 替换所有的 1
df_replaced = df.replace(to_replace=1, value=100)
# 用字符串 'z' 替换所有的 'a'
df_replaced = df_replaced.replace(to_replace='a', value='z')
# 使用字典替换多个值
df_replaced = df.replace({
2: 200,
'b': 'y'
})
# 使用正则表达式替换 -- ^a$ 表示:整个字符串必须恰好是一个小写字母 a
df_replaced = df.replace(to_replace=r'^a$', value='z', regex=True)
print(df_replaced)
pivot()
用于改变表格形状格式
DataFrame.pivot(columns, index=typing.Literal[
columns:作为新 DataFrame 的行索引的列名。可以是单个列名或列名列表index:作为新 DataFrame 的列标签的列名。可以是单个列名或列名列表values:作为新 DataFrame 的值的列名。可以是单个列名或列名列表
import pandas as pd
# 创建一个 DataFrame
df = pd.DataFrame({
'foo': ['one', 'one', 'one', 'two', 'two', 'two'],
'bar': ['A', 'B', 'C', 'A', 'B', 'C'],
'baz': [1, 2, 3, 4, 5, 6],
'zoo': ['x', 'y', 'z', 'q', 'w', 't']
})
# 打印原始 DataFrame
print(df)
# 使用 pivot 方法对 DataFrame 进行重塑,其中 foo 作为行索引,bar 作为列索引,baz 作为值
print("\n")
res1 = df.pivot(index='foo', columns='bar', values='baz')
# 打印重塑后的 DataFrame
print(res1)
# 使用 pivot 方法对 DataFrame 进行重塑,其中 foo 作为行索引,bar 作为列索引,baz、zoo 作为值
print("\n")
res2 = df.pivot(index='foo', columns='bar', values=['baz', 'zoo'])
# 打印重塑后的DataFrame
print(res2)
运行结果:
foo bar baz zoo
0 one A 1 x
1 one B 2 y
2 one C 3 z
3 two A 4 q
4 two B 5 w
5 two C 6 t
bar A B C
foo
one 1 2 3
two 4 5 6
baz zoo
bar A B C A B C
foo
one 1 2 3 x y z
two 4 5 6 q w t
melt()
用于改变表格形状格式
DataFrame.melt(id_vars=None, value_vars=None, var_name=None, value_name='value', col_level=None, ignore_index=True)
id_vars:保持不变的列名或列名列表value_vars:字符串或字符串列表,可选。要重塑的列名或列名列表。这些列的值将被展平到新的行中var_name:新的列名,该列数据为原来列的名称。默认值为None,表示使用默认名称(指定的是新生成的列的名字,而这列里面存放的是原来 DataFrame 的列名)value_name:字符串。新的列名,用于存储原来列的值。默认值为'value'col_level:整数或列标签,可选。如果DataFrame的列是多级索引,指定要使用的级别。默认值为None,表示使用所有级别ignore_index:是否忽略原来的索引,重新生成一个新的默认整数索引。默认值为True
import pandas as pd
# 创建一个DataFrame
df = pd.DataFrame({
'A': {0: 'a', 1: 'b', 2: 'c'},
'B': {0: 1, 1: 3, 2: 5},
'C': {0: 2, 1: 4, 2: 6}
})
# 打印原始 DataFrame
print(df)
# 使用 melt 方法对 DataFrame 进行重塑
res1 = df.melt(id_vars=['A'], value_vars=['B'], # A 列不变,重塑 B 列
var_name='myVarname', value_name='myValnames' # 新列名为 myVarname,存储原列名 B;新列名为 myValnames,存储原列 B 中的值
)
# 打印重塑后的 DataFrame
print(res1)
运行结果:
A B C
0 a 1 2
1 b 3 4
2 c 5 6
A myVarname myValnames
0 a B 1
1 b B 3
2 c B 5
pivot_table()
用于生成一个指定格式的数据透视表
DataFrame.pivot_table(values=None, index=None, columns=None, aggfunc='mean', fill_value=None, margins=False, dropna=True, margins_name='All', observed=False, sort=True)
values:要聚合的列名或列名列表。如果未指定,则使用所有数值列index:作为新DataFrame的行索引的列名或列名列表columns:作为新DataFrame的列标签的列名或列名列表aggfunc:聚合函数,可以是:- 单个函数(如
'mean'、'sum'、'count'等) - 函数列表(如
['mean', 'sum']) - 字典,键是列名,值是聚合函数
- 单个函数(如
fill_value:用于填充缺失值的值。默认值为Nonemargins:是否添加总计行和总计列。默认值为Falsedropna:是否从结果中删除包含缺失值的行。默认值为Truemargins_name:总计行和总计列的名称。默认值为'All'observed:是否仅显示已观察到的类别。默认值为Falsesort:是否对结果进行排序。默认值为True
import numpy as np
import pandas as pd
# 创建一个 DataFrame
df = pd.DataFrame({
"A": ["foo", "foo", "foo", "foo", "foo",
"bar", "bar", "bar", "bar"],
"B": ["one", "one", "one", "two", "two",
"one", "one", "two", "two"],
"C": ["small", "large", "large", "small",
"small", "large", "small", "small",
"large"],
"D": [1, 2, 2, 3, 3, 4, 5, 6, 7],
"E": [2, 4, 5, 5, 6, 6, 8, 9, 9]
})
# 打印原始 DataFrame
print(df)
# 使用 pivot_table 方法创建一个数据透视表
# D为值,AB为行标签,C为列标签,求和
table = df.pivot_table(values='D', index=['A', 'B'], columns=['C'], aggfunc=np.sum)
# 打印数据透视表
print(table)
运行结果:
A B C D E
0 foo one small 1 2
1 foo one large 2 4
2 foo one large 2 5
3 foo two small 3 5
4 foo two small 3 6
5 bar one large 4 6
6 bar one small 5 8
7 bar two small 6 9
8 bar two large 7 9
C large small
A B
bar one 4.0 5.0
two 7.0 6.0
foo one 4.0 1.0
two NaN 6.0
astype()
用于转换 DataFrame 中指定列的数据类型
DataFrame.astype(dtype, copy=None, errors='raise')
dtype:新的数据类型,可以是字典或数据类型。如果是字典,则键是列名,值是要转换为的数据类型。如果指定为单一数据类型,则所有列都将转换为该类型copy:布尔值,默认为None。如果为True,则在转换数据之前创建数据的副本。如果为False,则尽可能地避免复制,但这可能会影响到输入数据的原始 DataFrame。如果为None(默认值),则仅在需要时复制数据errors:{'raise', 'ignore'},默认为 'raise'。控制当转换失败时的行为。如果为 'raise',则在无法转换数据时抛出异常;如果为 'ignore',则在无法转换数据时保持原始数据类型不变
import pandas as pd
# 创建一个示例 DataFrame
df = pd.DataFrame({
'A': [1, 2, 3],
'B': [4.5, 5.5, 6.5],
'C': ['7', '8', '9']
})
# 打印原始 DataFrame
print(df)
# 将列 'A' 转换为浮点数类型
df['A'] = df['A'].astype(float)
# 使用字典将多列转换为不同的数据类型
# 将列 'B' 转换为整数类型,列 'C' 也转换为整数类型
df = df.astype({
'B': int,
'C': int
})
# 打印转换后的 DataFrame
print(df)
# 打印 DataFrame 中各列的数据类型
print(df.dtypes)
运行结果:
A B C
0 1 4.5 7
1 2 5.5 8
2 3 6.5 9
A B C
0 1.0 4 7
1 2.0 5 8
2 3.0 6 9
A float64
B int64
C int64
dtype: object
(3)数据排序
sort_values()
用于根据一个或多个列的值对 DataFrame 进行排序
DataFrame.sort_values(by, axis=0, ascending=True, inplace=False, kind='quicksort', na_position='last', ignore_index=False, key=None)
by:用于排序的列名或列名列表。axis:{0 或 'index', 1 或 'columns'},默认为 0。沿着哪个轴进行排序。ascending:排序的方向,True 表示升序,False 表示降序,默认为 True。inplace:是否在原地修改 DataFrame。kind:{'quicksort', 'mergesort', 'heapsort', 'stable'},默认为 'quicksort'。排序算法。na_position:{'first', 'last'},默认为 'last'。缺失值的放置位置。ignore_index:布尔值,默认为 False。是否忽略原来的索引,重新生成一个新的默认整数索引。key:函数,默认为 None。应用于by中每个列的函数,排序将基于函数的返回值。
import numpy as np
import pandas as pd
# 创建一个示例 DataFrame
df = pd.DataFrame({
'col1': ['A', 'A', 'B', np.nan, 'D', 'C'],
'col2': [2, 1, 9, 8, 7, 4],
'col3': [0, 1, 9, 4, 2, 3],
'col4': ['a', 'B', 'c', 'D', 'e', 'F']
})
# 打印原始 DataFrame
print(df)
# 根据 'col1' 列对 DataFrame 进行排序
res1 = df.sort_values(by=['col1'])
# 打印排序后的DataFrame
print(res1)
# 根据 'col1' 和 'col2' 列对 DataFrame 进行排序
res2 = df.sort_values(by=['col1', 'col2'])
# 打印排序后的 DataFrame
print(res2)
运行结果:
col1 col2 col3 col4
0 A 2 0 a
1 A 1 1 B
2 B 9 9 c
3 NaN 8 4 D
4 D 7 2 e
5 C 4 3 F
col1 col2 col3 col4
0 A 2 0 a
1 A 1 1 B
2 B 9 9 c
5 C 4 3 F
4 D 7 2 e
3 NaN 8 4 D
col1 col2 col3 col4
1 A 1 1 B
0 A 2 0 a
2 B 9 9 c
5 C 4 3 F
4 D 7 2 e
3 NaN 8 4 D
sort_index()
用于根据索引对 DataFrame 进行排序
DataFrame.sort_index(axis=0, level=None, ascending=True, inplace=False, kind='quicksort', na_position='last', sort_remaining=True, ignore_index=False, key=None)
axis:{0 或 'index', 1 或 'columns'},默认为 0。表示沿着哪个轴进行排序。0按照行标签排序,1按照列标签排序level:如果索引是多级索引,指定要排序的级别。可以是整数或整数列表ascending:默认为True。表示排序是升序还是降序inplace:是否在原地修改DataFramekind:{'quicksort', 'mergesort', 'heapsort', 'stable'},默认为 'quicksort'。排序算法na_position:{'first', 'last'},默认为 'last'。缺失值的位置放置。sort_remaining:是否对剩余的级别进行排序。仅在多级索引时有效。默认值为Trueignore_index:是否忽略原来的索引,重新生成一个新的默认整数索引。默认值为Falsekey:函数,默认为None。应用于索引的函数,排序将基于函数的返回值
import pandas as pd
import numpy as np
# 创建一个多级索引的 DataFrame
arrays = [np.array(['qux', 'qux', 'foo', 'foo']),
np.array(['two', 'one', 'two', 'one'])]
df = pd.DataFrame({'A': [1, 2, 3, 4], 'B': [4, 3, 2, 1]}, index=arrays)
print(df)
# 按第一层索引升序排序
df_sorted_by_first_level = df.sort_index(level=0)
print(df_sorted_by_first_level)
# 按第二层索引降序排序
df_sorted_by_second_level_desc = df.sort_index(level=1, ascending=False)
print(df_sorted_by_second_level_desc)
# 按整个索引升序排序
df_sorted_by_full_index = df.sort_index(ascending=True)
print(df_sorted_by_full_index)
运行结果:
A B
qux two 1 4
one 2 3
foo two 3 2
one 4 1
A B
foo one 4 1
two 3 2
qux one 2 3
two 1 4
A B
qux two 1 4
foo two 3 2
qux one 2 3
foo one 4 1
A B
foo one 4 1
two 3 2
qux one 2 3
two 1 4
(4)数据筛选
可以使用布尔数组进行索引,选择满足条件的数据
import pandas as pd
data = {
'姓名': ['小明', '小红', '小刚'],
'年龄': [20, 18, 22],
'成绩': [85, 90, 88]
}
df = pd.DataFrame(data)
# 使用布尔索引选择成绩大于或等于90的学生
high_scores = df[df['成绩'] >= 90]
print(high_scores)
(5)数据拼接
concat()
用于沿一个轴将多个 pandas 对象连接在一起
pandas.concat(objs, axis=0, join='outer', ignore_index=False, keys=None, levels=None, names=None, verify_integrity=False, sort=False, copy=True)
objs:要连接的对象列表axis:{0, 1, 'index', 'columns'},默认为 0join:连接方式。可以是:'outer':取所有索引的并集'inner':取所有索引的交集
ignore_index:是否忽略原来的索引,重新生成一个新的默认整数索引。默认值为Falsekeys:用于生成多级索引的键列表。每个键对应一个对象levels:用于多级索引的级别列表。通常与keys一起使用names:用于多级索引的名称列表。通常与keys一起使用verify_integrity:是否验证最终的DataFrame是否有重复的索引。默认值为Falsesort:是否对结果按照列名进行升序排序。默认值为Falsecopy:是否复制数据
import pandas as pd
# 创建两个 DataFrame
df1 = pd.DataFrame({'A': ['A0', 'A1', 'A2', 'A3'],
'B': ['B0', 'B1', 'B2', 'B3'],
'C': ['C0', 'C1', 'C2', 'C3'],
'D': ['D0', 'D1', 'D2', 'D3']},
index=[0, 1, 2, 3])
df2 = pd.DataFrame({'A': ['A4', 'A5', 'A6', 'A7'],
'B': ['B4', 'B5', 'B6', 'B7'],
'C': ['C4', 'C5', 'C6', 'C7'],
'F': ['F4', 'F5', 'F6', 'F7']},
index=[4, 5, 6, 7])
# 沿着竖直方向(按行)拼接两个 DataFrame
result = pd.concat([df1, df2], axis=0, ignore_index=True)
print(result)
运行结果:
A B C D F
0 A0 B0 C0 D0 NaN
1 A1 B1 C1 D1 NaN
2 A2 B2 C2 D2 NaN
3 A3 B3 C3 D3 NaN
4 A4 B4 C4 NaN F4
5 A5 B5 C5 NaN F5
6 A6 B6 C6 NaN F6
7 A7 B7 C7 NaN F7
merge()
用于根据一个或多个相同的键将两个 DataFrame 对象连接起来
DataFrame.merge(right, how='inner', on=None, left_on=None, right_on=None, left_index=False, right_index=False, sort=False, suffixes=('_x', '_y'), copy=None, indicator=False, validate=None)
right:另一个 DataFrame 对象how:{'left', 'right', 'outer', 'inner', 'cross'},默认为 'inner'。确定连接的类型:'left':使用左侧(调用 merge 的 DataFrame)的索引进行左连接'right':使用右侧(参数 right 中的 DataFrame)的索引进行右连接'outer':使用两个DataFrame的并集连接'inner':使用两个DataFrame的交集连接
on:用于合并的列名。如果left_on和right_on都没有指定,则使用onleft_on:左侧 DataFrame 中用于合并的列名。不与on同时使用right_on:右侧 DataFrame 中用于合并的列名。不与on同时使用left_index:是否使用左侧 DataFrame 的索引作为合并键。默认值为False。不与on同时使用right_index:是否使用右侧 DataFrame 的索引作为合并键。默认值为False。不与on同时使用sort:是否对结果进行排序。默认值为Falsesuffixes:用于重命名重复列的后缀。默认值为('_x', '_y')copy:是否复制数据。默认值为None,表示根据需要自动决定是否复制indicator:是否添加一个指示器列,显示每行来自哪个 DataFrame。默认值为Falsevalidate:检查合并键。可以是:'one_to_one':检查合并键在两者中是否唯一'one_to_many':检查合并键在左侧是否唯一'many_to_one':检查合并键在右侧是否唯一'many_to_many':不检查
import pandas as pd
# 创建两个 DataFrame
df1 = pd.DataFrame({'key': ['A', 'B', 'C', 'D'],
'value': [1, 2, 3, 4]},
index=['a', 'b', 'c', 'd'])
df2 = pd.DataFrame({'key': ['B', 'D', 'D', 'E'],
'value': [5, 6, 7, 8]},
index=['a', 'c', 'e', 'f'])
# 使用内连接(inner join)合并两个 DataFrame
result = df1.merge(df2, on='key', how='inner', suffixes=('_left', '_right'))
print(result)
运行结果:
key value_left value_right
0 B 2 5
1 D 4 6
2 D 4 7
join()
用于将两个对象的列连接起来
DataFrame.join(other, on=None, how='left', lsuffix='', rsuffix='', sort=False, validate=None)
other:另一个 DataFrame 对象on:用于连接的列名how:{'left', 'right', 'outer', 'inner'},默认为 'left'。确定连接的类型:'left':使用左侧(调用 join 的 DataFrame)的索引进行左连接'right':使用右侧(参数 other 中的 DataFrame)的索引进行右连接'outer':使用两个 DataFrame 的索引的并集进行全外连接'inner':使用两个 DataFrame 的索引的交集进行内连接
lsuffix:用于重命名重复列的左后缀。默认值为空字符串''rsuffix:用于重命名重复列的右后缀。默认值为空字符串''sort:是否对结果进行排序。默认值为Falsevalidate:检查合并键。可以是:'one_to_one':检查合并键在两者中是否唯一'one_to_many':检查合并键在左侧是否唯一'many_to_one':检查合并键在右侧是否唯一'many_to_many':不检查
import pandas as pd
# 创建两个 DataFrame
df1 = pd.DataFrame({'key': ['A', 'B', 'C', 'D'],
'value': [1, 2, 3, 4]},
index=['k0', 'k1', 'k2', 'k3'])
df2 = pd.DataFrame({'value2': [5, 6, 7, 8]},
index=['k1', 'k2', 'k3', 'k4'])
# 使用左连接(left join)根据索引合并两个 DataFrame
result = df1.join(df2, how='left')
print(result)
5. 统计
(1)count
用于计算 DataFrame 中非 NaN 值的数量
DataFrame.count(axis=0, numeric_only=False)
axis:{0 或 'index', 1 或 'columns'},决定统计的方向。- 如果
axis=0或axis='index',则对每列进行计数,返回一个 Series,其索引为列名,值为每列非 NaN 值的数量。 - 如果
axis=1或axis='columns',则对每行进行计数,返回一个 Series,其索引为行索引,值为每行非 NaN 值的数量。
- 如果
numeric_only:是否只计算数值列中的非 NaN 值的数量,忽略非数值列,默认为 False。
import pandas as pd
import numpy as np
# 创建一个包含 NaN 值的 DataFrame
df = pd.DataFrame({
'A': [1, 2, np.nan, 4],
'B': [5, np.nan, np.nan, 8],
'C': ['foo', 'bar', 'baz', np.nan]
})
# 计算每列非 NaN 值的数量
count_per_column = df.count()
print("Count per column:")
print(count_per_column)
# 计算每行非 NaN 值的数量
count_per_row = df.count(axis='columns')
print("\nCount per row:")
print(count_per_row)
# 只计算数值列的非 NaN 值的数量
count_numeric_only = df.count(numeric_only=True)
print("\nCount numeric only:")
print(count_numeric_only)
运行结果:
Count per column:
A 3
B 2
C 3
dtype: int64
Count per row:
0 3
1 2
2 1
3 2
dtype: int64
Count numeric only:
A 3
B 2
dtype: int64
(2)sum
用于计算 DataFrame 中数值的总和
DataFrame.sum(axis=0, skipna=True, numeric_only=False, min_count=0, **kwargs)
以下是从图片中提取的文字,已按照 Markdown 格式排版:
axis: {0 或 'index', 1 或 'columns', None},默认为 0。这个参数决定了求和是在哪个轴上进行:- 如果
axis=0或axis='index',则对每列进行求和,返回一个 Series,其索引为列名,值为每列的总和。 - 如果
axis=1或axis='columns',则对每行进行求和,返回一个 Series,其索引为行索引,值为每行的总和。
- 如果
skipna: 布尔值,默认为 True。如果为 True,则在计算总和时会忽略 NaN 值。numeric_only: 布尔值,默认为 False。如果为 True,则只对数值列进行求和,忽略非数值列。min_count: int,默认为 0。这个参数指定了在计算总和之前,至少需要非 NaN 值的最小数量。如果某个分组中的非 NaN 值的数量小于min_count,则结果为 NaN。**kwargs: 其他关键字参数。这些参数通常用于兼容性或特殊用途,通常不需要。
import pandas as pd
import numpy as np
# 创建一个包含 NaN 值的 DataFrame
df = pd.DataFrame({
'A': [1, 2, np.nan, 4],
'B': [5, np.nan, np.nan, 8],
'C': ['foo', 'bar', 'baz', 'qux']
})
# 计算每列的总和
sum_per_column = df.sum()
print("Sum per column:")
print(sum_per_column)
# # 计算每行的总和
# sum_per_row = df.sum(axis='columns')
# print("\nSum per row:")
# print(sum_per_row) # 报错:'float' and 'str' 不能相加
# 只计算数值列的总和
sum_numeric_only = df.sum(numeric_only=True)
print("\nSum numeric only:")
print(sum_numeric_only)
# 使用 min_count 参数
sum_with_min_count = df.sum(min_count=2)
print("\nSum with min_count=2:")
print(sum_with_min_count)
运行结果:
Sum per column:
A 7.0
B 13.0
C foobarbazqux
dtype: object
Sum numeric only:
A 7.0
B 13.0
dtype: float64
Sum with min_count=2:
A 7.0
B 13.0
C foobarbazqux
dtype: object
(3)mean
用于计算 DataFrame 中数值的平均值
DataFrame.mean(axis=0, skipna=True, numeric_only=False, **kwargs)
axis: {0 或 'index', 1 或 'columns', None},默认为 0。这个参数决定了计算平均值是在哪个轴上进行:- 如果
axis=0或axis='index',则对每列进行计算,返回一个 Series,其索引为列名,值为每列的平均值。 - 如果
axis=1或axis='columns',则对每行进行计算,返回一个 Series,其索引为行索引,值为每行的平均值。
- 如果
skipna: 布尔值,默认为 True。如果为 True,则在计算平均值时会忽略 NaN 值。numeric_only: 布尔值,默认为 False。如果为 True,则只对数值列进行计算,忽略非数值列。**kwargs: 其他关键字参数。这些参数通常用于兼容性或特殊用途,通常不需要。
import pandas as pd
import numpy as np
# 创建一个包含 NaN 值的 DataFrame
df = pd.DataFrame({
'A': [1, 2, np.nan, 4],
'B': [5, np.nan, np.nan, 8],
'C': ['foo', 'bar', 'baz', 'qux'] # 非数值列
})
# # 计算每列的平均值
# mean_per_column = df.mean()
# print("Mean per column:")
# print(mean_per_column) # 数据中有字符串,无法获取结果,会报错
#
# # 计算每行的平均值
# mean_per_row = df.mean(axis='columns')
# print("\nMean per row:")
# print(mean_per_row) # 数据中有字符串,无法获取结果,会报错
# 只计算数值列的平均值
mean_numeric_only = df.mean(numeric_only=True)
print("\nMean numeric only:")
print(mean_numeric_only)
运行结果:
Mean numeric only:
A 2.333333
B 6.500000
dtype: float64
(4)median
用于计算 DataFrame 中数值的中位数
DataFrame.median(axis=0, skipna=True, numeric_only=False, **kwargs)
axis: {0 或 'index', 1 或 'columns'},默认为 0。这个参数决定了计算中位数是在哪个轴上进行:- 如果
axis=0或axis='index',则对每列进行计算,返回一个 Series,其索引为列名,值为每列的中位数。 - 如果
axis=1或axis='columns',则对每行进行计算,返回一个 Series,其索引为行索引,值为每行的中位数。
- 如果
skipna: 布尔值,默认为 True。如果为 True,则在计算中位数时会忽略 NaN 值。numeric_only: 布尔值,默认为 False。如果为 True,则只对数值列进行计算,忽略非数值列。**kwargs: 其他关键字参数。这些参数通常用于兼容性或特殊用途,通常不需要。
import pandas as pd
import numpy as np
# 创建一个包含 NaN 值的 DataFrame
df = pd.DataFrame({
'A': [1, 2, np.nan, 4],
'B': [5, np.nan, 7, 8],
# 'C': ['foo', 'bar', 'baz', 'qux'] # 非数值列
})
# 计算每列的中位数
median_per_column = df.median()
print("Median per column:")
print(median_per_column)
# 计算每行的中位数
median_per_row = df.median(axis='columns')
print("\nMedian per row:")
print(median_per_row)
# 只计算数值列的中位数
median_numeric_only = df.median(numeric_only=True)
print("\nMedian numeric only:")
print(median_numeric_only)
运行结果:
Median per column:
A 2.0
B 7.0
dtype: float64
Median per row:
0 3.0
1 2.0
2 7.0
3 6.0
dtype: float64
Median numeric only:
A 2.0
B 7.0
dtype: float64
(5)min
用于计算 DataFrame 中数值的最小值
DataFrame.min(axis=0, skipna=True, numeric_only=False, **kwargs)
axis: {0 或 'index', 1 或 'columns'},默认为 0。这个参数决定了计算最小值是在哪个轴上进行:- 如果
axis=0或axis='index',则对每列进行计算,返回一个 Series,其索引为列名,值为每列的最小值。 - 如果
axis=1或axis='columns',则对每行进行计算,返回一个 Series,其索引为行索引,值为每行的最小值。
- 如果
skipna: 布尔值,默认为 True。如果为 True,则在计算最小值时会忽略 NaN 值。numeric_only: 布尔值,默认为 False。如果为 True,则只对数值列进行计算,忽略非数值列。**kwargs: 其他关键字参数。这些参数通常用于兼容性或特殊用途,通常不需要。
import pandas as pd
import numpy as np
# 创建一个包含 NaN 值的 DataFrame
df = pd.DataFrame({
'A': [1, 2, np.nan, 4],
'B': [5, np.nan, 7, 8],
'C': [6, 9, 3, 2],
# 'C': ['foo', 'bar', 'baz', 'qux'] # 非数值列
})
# 计算每列的最小值
min_per_column = df.min()
print("Min per column:")
print(min_per_column)
# 计算每行的最小值
min_per_row = df.min(axis='columns')
print("\nMin per row:")
print(min_per_row)
# 只计算数值列的最小值
min_numeric_only = df.min(numeric_only=True)
print("\nMin numeric only:")
print(min_numeric_only)
运行结果:
Min per column:
A 1.0
B 5.0
C 2.0
dtype: float64
Min per row:
0 1.0
1 2.0
2 3.0
3 2.0
dtype: float64
Min numeric only:
A 1.0
B 5.0
C 2.0
dtype: float64
(6)max
用于计算 DataFrame 中数值的最大值
DataFrame.max(axis=0, skipna=True, numeric_only=False, **kwargs)
axis: {0 或 'index', 1 或 'columns'},默认为 0。这个参数决定了计算最大值是在哪个轴上进行:- 如果
axis=0或axis='index',则对每列进行计算,返回一个 Series,其索引为列名,值为每列的最大值。 - 如果
axis=1或axis='columns',则对每行进行计算,返回一个 Series,其索引为行索引,值为每行的最大值。
- 如果
skipna: 布尔值,默认为 True。如果为 True,则在计算最大值时会忽略 NaN 值。numeric_only: 布尔值,默认为 False。如果为 True,则只对数值列进行计算,忽略非数值列。**kwargs: 其他关键字参数。这些参数通常用于兼容性或特殊用途,通常不需要。
import pandas as pd
import numpy as np
# 创建一个包含 NaN 值的 DataFrame
df = pd.DataFrame({
'A': [1, 2, np.nan, 4],
'B': [5, np.nan, 7, 8],
'C': [6, 9, 3, 2],
# 'C': ['foo', 'bar', 'baz', 'qux'] # 非数值列
})
# 计算每列的最大值
max_per_column = df.max()
print("Max per column:")
print(max_per_column)
# 计算每行的最大值
max_per_row = df.max(axis='columns')
print("\nMax per row:")
print(max_per_row)
# 只计算数值列的最大值
max_numeric_only = df.max(numeric_only=True)
print("\nMax numeric only:")
print(max_numeric_only)
运行结果:
Max per column:
A 4.0
B 8.0
C 9.0
dtype: float64
Max per row:
0 6.0
1 9.0
2 7.0
3 8.0
dtype: float64
Max numeric only:
A 4.0
B 8.0
C 9.0
dtype: float64
(7)var
用于计算 DataFrame 中数值的方差
DataFrame.var(axis=0, skipna=True, ddof=1, numeric_only=False, **kwargs)
axis: {0 或 'index', 1 或 'columns', None},默认为 0。这个参数决定了计算方差是在哪个轴上进行:- 如果
axis=0或axis='index',则对每列进行计算,返回一个 Series,其索引为列名,值为每列的方差。 - 如果
axis=1或axis='columns',则对每行进行计算,返回一个 Series,其索引为行索引,值为每行的方差。
- 如果
skipna: 布尔值,默认为 True。如果为 True,则在计算方差时会忽略 NaN 值。ddof: 整数,默认为 1。Delta Degrees of Freedom,计算样本方差时使用的无偏估计的自由度修正。对于整个群体的方差,ddof应该设置为 0。numeric_only: 布尔值,默认为 False。如果为 True,则只对数值列进行计算,忽略非数值列。**kwargs: 其他关键字参数。这些参数通常用于兼容性或特殊用途,通常不需要。
import pandas as pd
import numpy as np
# 创建一个包含 NaN 值的 DataFrame
df = pd.DataFrame({
'A': [1, 2, np.nan, 4],
'B': [5, np.nan, 7, 8],
'C': [6, 9, 3, 2],
# 'C': ['foo', 'bar', 'baz', 'qux'] # 非数值列
})
# 计算每列的方差
var_per_column = df.var()
print("Variance per column:")
print(var_per_column)
# 计算每行的方差
var_per_row = df.var(axis='columns')
print("\nVariance per row:")
print(var_per_row)
# 只计算数值列的方差,并且使用无偏估计(ddof=1)
var_numeric_only = df.var(numeric_only=True, ddof=1)
print("\nVariance numeric only with ddof=1:")
print(var_numeric_only)
运行结果:
Variance per column:
A 2.333333
B 2.333333
C 10.000000
dtype: float64
Variance per row:
0 7.000000
1 24.500000
2 8.000000
3 9.333333
dtype: float64
Variance numeric only with ddof=1:
A 2.333333
B 2.333333
C 10.000000
dtype: float64
(8)std
用于计算 DataFrame 中数值的标准差
DataFrame.std(axis=0, skipna=True, ddof=1, numeric_only=False, **kwargs)
axis: {0 或 'index', 1 或 'columns', None},默认为 0。这个参数决定了计算标准差是在哪个轴上进行:- 如果
axis=0或axis='index',则对每列进行计算,返回一个 Series,其索引为列名,值为每列的标准差。 - 如果
axis=1或axis='columns',则对每行进行计算,返回一个 Series,其索引为行索引,值为每行的标准差。
- 如果
skipna: 布尔值,默认为 True。如果为 True,则在计算标准差时会忽略 NaN 值。ddof: 整数,默认为 1。Delta Degrees of Freedom,计算样本标准差时使用的无偏估计的自由度修正。对于整个群体的标准差,ddof应该设置为 0。numeric_only: 布尔值,默认为 False。如果为 True,则只对数值列进行计算,忽略非数值列。**kwargs: 其他关键字参数。这些参数通常用于兼容性或特殊用途,通常不需要。
import pandas as pd
import numpy as np
# 创建一个包含 NaN 值的 DataFrame
df = pd.DataFrame({
'A': [1, 2, np.nan, 4],
'B': [5, np.nan, 7, 8],
'C': [6, 9, 3, 2],
# 'C': ['foo', 'bar', 'baz', 'qux'] # 非数值列
})
# 计算每列的标准差
std_per_column = df.std()
print("Standard deviation per column:")
print(std_per_column)
# 计算每行的标准差
std_per_row = df.std(axis='columns')
print("\nStandard deviation per row:")
print(std_per_row)
# 只计算数值列的标准差,并且使用无偏估计(ddof=1)
std_numeric_only = df.std(numeric_only=True, ddof=1)
print("\nStandard deviation numeric only with ddof=1:")
print(std_numeric_only)
运行结果:
Standard deviation per column:
A 1.527525
B 1.527525
C 3.162278
dtype: float64
Standard deviation per row:
0 2.645751
1 4.949747
2 2.828427
3 3.055050
dtype: float64
Standard deviation numeric only with ddof=1:
A 1.527525
B 1.527525
C 3.162278
dtype: float64
(9)quantile
用于计算 DataFrame 中数值的分位数
DataFrame.quantile(q=0.5, axis=0, numeric_only=False, interpolation='linear', method='single')
q: 可以是单个浮点数或浮点数列表,默认为 0.5。要计算的的分位数,应该在 0 到 1 之间。例如,q=0.5表示中位数。axis: {0 或 'index', 1 或 'columns'},默认为 0。这个参数决定了计算分位数是在哪个轴上进行:- 如果
axis=0或axis='index',则对每列进行计算,返回一个 Series 或 DataFrame,其索引为列名,值为每列的分位数。 - 如果
axis=1或axis='columns',则对每行进行计算,返回一个 Series 或 DataFrame,其索引为行索引,值为每行的分位数。
- 如果
numeric_only: 布尔值,默认为 False。如果为 True,则只对数值列进行计算,忽略非数值列。interpolation: {'linear', 'lower', 'higher', 'midpoint', 'nearest'},默认为 'linear'。这个参数决定了分位数在数据不包含精确分位数值时的插值方法:- 'linear': 线性插值。
- 'lower': 选择小于分位数的最大值。
- 'higher': 选择大于分位数的最小值。
- 'midpoint': 选择两个相邻数据的中间值。
- 'nearest': 选择最接近分位数的值。
method: {'single', 'table'},默认为 'single'。这个参数决定了计算分位数的方法:- 'single': 对每列或每行单独计算分位数。
- 'table': 使用整个表的分位数。选择table时,插值方法只能是higher、lower、nearest之一。
import pandas as pd
# 创建一个DataFrame
data = {
'col1': [10, 20, 30, 40, 50],
'col2': [15, 25, 35, 45, 55],
'col3': [20, 30, 40, 50, 60]
}
df = pd.DataFrame(data)
# 按列方向计算0.5分位数(中位数)
col_median = df.quantile(0.5, axis=0)
print("按列方向的0.5分位数(中位数):\n", col_median)
# 按行方向计算0.5分位数(中位数)
row_median = df.quantile(0.5, axis=1)
print("按行方向的0.5分位数(中位数):\n", row_median)
运行结果:
按列方向的0.5分位数(中位数):
col1 30.0
col2 35.0
col3 40.0
Name: 0.5, dtype: float64
按行方向的0.5分位数(中位数):
0 15.0
1 25.0
2 35.0
3 45.0
4 55.0
Name: 0.5, dtype: float64
(10)cummax
用于计算 DataFrame 中数值的累积最大值
DataFrame.cummax(axis=0, skipna=True, *args, **kwargs)
axis: {0 或 'index', 1 或 'columns', None},默认为 0。这个参数决定了计算累积最大值是在哪个轴上进行:- 如果
axis=0或axis='index',则对每列进行计算,返回一个 DataFrame,其索引保持不变,每一列的值是自上而下(从第一行到当前行)的最大值 - 如果
axis=1或axis='columns',则对每行进行计算,返回一个 DataFrame,其列保持不变,每一行的值是自左向右(从第一列到当前列)的最大值
- 如果
skipna: 布尔值,默认为 True。如果为 True,则在计算累积最大值时忽略 NaN 值;如果为 False,则包含 NaN 值,可能导致结果中包含 NaN*args和**kwargs: 这些参数用于传递给底层方法的其他参数,通常不需要使用
import pandas as pd
import numpy as np
# 创建一个 DataFrame
df = pd.DataFrame({
'A': [1, 2, np.nan, 4, 5],
'B': [5, np.nan, 3, 2, 1],
})
# 计算每列的累积最大值
cummax_per_column = df.cummax(axis=0)
print("Cumulative max per column:")
print(cummax_per_column)
# 计算每行的累积最大值
cummax_per_row = df.cummax(axis=1)
print("\nCumulative max per row:")
print(cummax_per_row)
运行结果:
Cumulative max per column:
A B
0 1.0 5.0
1 2.0 NaN
2 NaN 5.0
3 4.0 5.0
4 5.0 5.0
Cumulative max per row:
A B
0 1.0 5.0
1 2.0 NaN
2 NaN 3.0
3 4.0 4.0
4 5.0 5.0
(11)cummin
用于计算 DataFrame 中数值的累积最小值
DataFrame.cummin(axis=0, skipna=True, *args, **kwargs)
axis: {0 或 'index', 1 或 'columns', None},默认为 0。这个参数决定了计算累积最小值是在哪个轴上进行:- 如果
axis=0或axis='index',则对每列进行计算,返回一个 DataFrame,其索引保持不变,每一列的值是自上而下(从第一行到当前行)的最小值 - 如果
axis=1或axis='columns',则对每行进行计算,返回一个 DataFrame,其列保持不变,每一行的值是自左向右(从第一列到当前列)的最小值
- 如果
skipna: 布尔值,默认为 True。如果为 True,则在计算累积最小值时忽略 NaN 值;如果为 False,则包含 NaN 值,可能导致结果中包含 NaN*args和**kwargs: 这些参数用于传递给底层方法的其他参数,通常不需要使用
import pandas as pd
import numpy as np
# 创建一个 DataFrame
df = pd.DataFrame({
'A': [3, 2, np.nan, 4, 1],
'B': [5, np.nan, 3, 2, 6],
'C': [6, 9, 3, 2, 5],
# 'C': ['foo', 'bar', 'baz', 'qux', 'quux'] # 非数值列
})
# 计算每列的累积最小值
cummin_per_column = df.cummin(axis=0)
print("Cumulative min per column:")
print(cummin_per_column)
# 计算每行的累积最小值
cummin_per_row = df.cummin(axis=1)
print("\nCumulative min per row:")
print(cummin_per_row)
运行结果:
Cumulative min per column:
A B C
0 3.0 5.0 6
1 2.0 NaN 6
2 NaN 3.0 3
3 2.0 2.0 2
4 1.0 2.0 2
Cumulative min per row:
A B C
0 3.0 3.0 3.0
1 2.0 NaN 2.0
2 NaN 3.0 3.0
3 4.0 2.0 2.0
4 1.0 1.0 1.0
(12)cumsum
用于计算 DataFrame 中数值的累积和。
DataFrame.cumsum(axis=0, skipna=True, *args, **kwargs)
-
axis: {0 或 ‘index’, 1 或 ‘columns’, None}, 默认为 0。这个参数决定了计算累积和是在哪个轴上进行:-
如果
axis=0或axis='index',则对每列进行计算,返回一个 DataFrame,其索引保持不变,每一列的值是自上而下(从第一行到当前行)的累积和。 -
如果
axis=1或axis='columns',则对每行进行计算,返回一个 DataFrame,其列保持不变,每一行的值是自左向右(从第一列到当前列)的累积和。
-
-
skipna: 布尔值,默认为 True。如果为 True,则在计算累积和时忽略 NaN 值;如果为 False,则包含 NaN 值,可能导致结果中包含 NaN。 -
*args和**kwargs: 这些参数用于传递给底层方法的其他参数,通常不需要使用。
import pandas as pd
import numpy as np
# 创建一个 DataFrame
df = pd.DataFrame({
'A': [3, 2, np.nan, 4, 1],
'B': [5, np.nan, 3, 2, 6],
'C': [6, 9, 3, 2, 5],
# 'C': ['foo', 'bar', 'baz', 'qux', 'quux'] # 非数值列
})
# 计算每列的累积和
cumsum_per_column = df.cumsum(axis=0)
print("Cumulative sum per column:")
print(cumsum_per_column)
# 计算每行的累积和
cumsum_per_row = df.cumsum(axis=1)
print("\nCumulative sum per row:")
print(cumsum_per_row)
运行结果:
Cumulative sum per column:
A B C
0 3.0 5.0 6
1 5.0 NaN 15
2 NaN 8.0 18
3 9.0 10.0 20
4 10.0 16.0 25
Cumulative sum per row:
A B C
0 3.0 8.0 14.0
1 2.0 NaN 11.0
2 NaN 3.0 6.0
3 4.0 6.0 8.0
4 1.0 7.0 12.0
(13)cumprod
用于计算 DataFrame 中数值的累积乘积。
DataFrame.cumprod(axis=0, skipna=True, *args, **kwargs)
-
axis: {0 或 ‘index’, 1 或 ‘columns’, None}, 默认为 0。这个参数决定了计算累积乘积是在哪个轴上进行:-
如果
axis=0或axis='index',则对每列进行计算,返回一个 DataFrame,其索引保持不变,每一列的值是自上而下(从第一行到当前行)的累积乘积。 -
如果
axis=1或axis='columns',则对每行进行计算,返回一个 DataFrame,其列保持不变,每一行的值是自左向右(从第一列到当前列)的累积乘积。
-
-
skipna: 布尔值,默认为 True。如果为 True,则在计算累积乘积时忽略 NaN 值;如果为 False,则包含 NaN 值,可能导致结果中包含 NaN。 -
*args和**kwargs: 这些参数用于传递给底层方法的其他参数,通常不需要使用。
import pandas as pd
import numpy as np
# 创建一个 DataFrame
df = pd.DataFrame({
'A': [3, 2, np.nan, 4, 1],
'B': [5, np.nan, 3, 2, 6],
'C': [6, 9, 3, 2, 5],
# 'C': ['foo', 'bar', 'baz', 'qux', 'quux'] # 非数值列
})
# 计算每列的累积乘积
cumprod_per_column = df.cumprod(axis=0)
print("Cumulative product per column:")
print(cumprod_per_column)
# 计算每行的累积乘积
cumprod_per_row = df.cumprod(axis=1)
print("\nCumulative product per row:")
print(cumprod_per_row)
运行结果:
Cumulative product per column:
A B C
0 3.0 5.0 6
1 6.0 NaN 54
2 NaN 15.0 162
3 24.0 30.0 324
4 24.0 180.0 1620
Cumulative product per row:
A B C
0 3.0 15.0 90.0
1 2.0 NaN 18.0
2 NaN 3.0 9.0
3 4.0 8.0 16.0
4 1.0 6.0 30.0
6. 分组与聚合
(1)groupby
用于将 DataFrame 分割成多个组,以便可以对这些组应用聚合函数或执行其他操作。
DataFrame.groupby(by=None, axis=0, level=None, as_index=True, sort=True, group_keys=True, observed=False, dropna=True)
-
by: 用于确定分组依据。 -
axis: {0 或 ‘index’, 1 或 ‘columns’},默认为 0。这个参数决定了分组是在哪个轴上进行。 -
level: 如果轴是多索引,则按指定的索引级别分组。 -
as_index: 布尔值,默认为 True。当为 True 时,分组名称将作为结果的索引;如果为 False,则结果会保持原有的 DataFrame 结构,分组名称会作为一个普通列出现。 -
sort: 布尔值,默认为 True。如果为 True,则对分组键进行排序;如果为 False,则不排序,保持原有的分组顺序。 -
group_keys: 布尔值,默认为 True。如果为 True,则将组键添加到聚合后的结果中;如果为False,则不添加。 -
observed: 布尔值,默认为 False。仅当分组依据是多索引且包含分类数据时适用,如果为True,则仅显示分类数据中的观察值。 -
dropna: 布尔值,默认为 True。如果为 True,并且by是一个列表,则排除任何含有 NaN 的组。
一级索引:
import pandas as pd
# 创建一个 DataFrame
df = pd.DataFrame({
'A': ['foo', 'bar', 'foo', 'bar', 'foo', 'bar', 'foo', 'foo'],
'B': ['one', 'one', 'two', 'three', 'two', 'two', 'one', 'three'],
'C': [1, 3, 2, 5, 4, 1, 2, 3],
'D': [2, 5, 3, 7, 6, 2, 4, 6]
})
# 按 'A' 和 'B' 列分组,并计算每组的平均值
grouped = df.groupby(['A', 'B']).mean()
print(grouped)
运行结果:
C D
A B
bar one 3.0 5.0
three 5.0 7.0
two 1.0 2.0
foo one 1.5 3.0
three 3.0 6.0
two 3.0 4.5
多级索引:
import pandas as pd
# 创建两个列表,它们将用作多级索引的级别
arrays = [['Falcon', 'Falcon', 'Parrot', 'Parrot'], # 第一级索引的值
['Captive', 'Wild', 'Captive', 'Wild']] # 第二级索引的值
# 使用arrays列表创建一个DataFrame,'Max Speed'列包含对应于多级索引的数据
df = pd.DataFrame({'Max Speed': [390., 350., 30., 20.]}, # 数据
index=arrays) # 使用arrays列表作为多级索引
# 打印原始DataFrame,以查看其结构和数据
print(df)
# 使用groupby方法按第一级索引(即'arrays'列表的第一个元素)分组
# level=0表示按照多级索引的第一级进行分组
res = df.groupby(level=0).mean() # 计算每个组(即每个不同的第一级索引值)的平均速度
# 打印分组后的平均值,显示每个动物的Max Speed的平均值
print(res)
运行结果:
Max Speed
Falcon Captive 390.0
Wild 350.0
Parrot Captive 30.0
Wild 20.0
Max Speed
Falcon 370.0
Parrot 25.0
(2)transform
对 DataFrame 或其中一个列应用一个函数,并返回一个与原始 DataFrame 具有相同索引的对象。此方法不会更改原始 DataFrame,而是返回一个新的 DataFrame,其中包含应用函数后的结果。
DataFrame.transform(func, axis=0, *args, **kwargs)
-
func: 函数,应用于每个组或列。这个函数可以是一个内置函数,比如numpy.mean,也可以是一个自定义函数。 -
axis: {0 或 ‘index’, 1 或 ‘columns’},默认为 0。这个参数决定了函数是在哪个轴上应用:-
如果
axis=0或axis='index',则函数按列应用。 -
如果
axis=1或axis='columns',则函数按行应用。
-
-
*args: 位置参数,将传递给func。 -
**kwargs: 关键字参数,将传递给func。
import pandas as pd
# 创建一个 DataFrame
df = pd.DataFrame({
'A': [1, 2, 3, 4, 5],
'B': [10, 20, 30, 40, 50],
'C': [100, 200, 300, 400, 500]
})
def square(x):
return x ** 2
# 调用transform函数,并将自定义函数带入
transformed_df = df.transform(square)
print(transformed_df)
运行结果:
A B C
0 1 100 10000
1 4 400 40000
2 9 900 90000
3 16 1600 160000
4 25 2500 250000
(3)agg
它允许你应用一个或多个聚合函数到 DataFrame 的列或行上,并返回聚合后的结果。
DataFrame.agg(func=None, axis=0, *args, **kwargs)
-
func: 函数或函数列表/字典,应用于 DataFrame 的列或行。如果传递一个函数,它将应用于所有列。如果传递一个函数列表或字典,则可以分别对不同的列应用不同的函数。可以使用的函数包括NumPy 的统计函数、Python 的内置函数、Pandas 的自定义聚合函数,或者自定义的 lambda 函数。 -
axis: {0 或 ‘index’, 1 或 ‘columns’},默认为 0。这个参数决定了聚合操作是在哪个轴上执行:-
如果
axis=0或axis='index',则函数按列应用(逐行操作)。 -
如果
axis=1或axis='columns',则函数按行应用(逐列操作)。
-
-
*args: 位置参数,将传递给func。 -
**kwargs: 关键字参数,将传递给func。
import pandas as pd
# 创建一个 DataFrame
df = pd.DataFrame({
'A': [1, 2, 3, 4, 5],
'B': [10, 20, 30, 40, 50]
})
# 应用单个聚合函数,计算每列的平均值
print("每列的平均值:")
result = df.agg('mean')
print(result)
# 对列 'A' 应用 'sum' 函数,对列 'B' 应用 'mean' 函数
print("\nA-sum,B-mean:")
result = df.agg({'A': 'sum', 'B': 'mean'})
print(result)
# 对所有列应用多个聚合函数
print("\n多个聚合函数:")
result = df.agg(['min', 'max', 'sum'])
print(result)
# 定义一个自定义函数
def custom_agg(x):
return (x.max() - x.min()) / x.std()
# 使用自定义函数进行聚合
print("\n自定义函数:")
result = df.agg(custom_agg)
print(result)
运行结果:
每列的平均值:
A 3.0
B 30.0
dtype: float64
A-sum,B-mean:
A 15.0
B 30.0
dtype: float64
多个聚合函数:
A B
min 1 10
max 5 50
sum 15 150
自定义函数:
A 2.529822
B 2.529822
dtype: float64
7. 数据可视化
(1)plot
用于绘制 DataFrame 数据图形,它允许用户直接从 DataFrame 创建各种类型的图表,而不需要使用其他绘图库(底层实际上使用了 Matplotlib)。
DataFrame.plot(*args, **kwargs)
以下是一些常见的 DataFrame.plot 方法的关键字参数:
-
kind: {‘line’, ‘bar’, ‘barh’, ‘hist’, ‘box’, ‘kde’, ‘density’, ‘area’, ‘pie’, ‘scatter’, ‘hexbin’},默认为‘line’。这个参数决定了要绘制哪种类型的图表。 -
ax: Matplotlib axes 对象,可选。如果提供,则绘图将在指定的 axes 对象上进行。 -
subplots: 布尔值,默认为 False。如果为 True,则每个数值列将绘制在其自己的子图中。 -
sharex: 布尔值,默认为 False。如果为 True,并且subplots为 True,则所有子图共享相同的x 轴。 -
sharey: 布尔值,默认为 False。如果为 True,并且subplots为 True,则所有子图共享相同的y 轴。 -
layout: 元组(行数,列数),可选。用于安排子图的布局。 -
figsize: 元组(宽度,高度),可选。用于设置图表的大小。 -
use_index: 布尔值,默认为 True。如果为 True,则将 DataFrame 的索引用作 x 轴。 -
title: 字符串,可选。图表的标题。 -
grid: 布尔值,默认为 None。如果为 True,则在图表上显示网格线。
import pandas as pd
import matplotlib.pyplot as plt
# 创建一个 DataFrame
df = pd.DataFrame({
'A': [1, 2, 3, 4, 5],
'B': [10, 20, 30, 40, 50]
})
# 绘制线图
df.plot(kind='line')
# 显示图像
plt.show()

(2)hist
用于绘制 DataFrame 中数据的直方图
DataFrame.hist(column=None, by=None, grid=True, xlabelsize=None, xrot=None, ylabelsize=None, yrot=None, ax=None, sharex=False, sharey=False, figsize=None, layout=None, bins=10, backend=None, legend=False, **kwargs)
-
column: 字符串或字符串列表,可选。用于指定要绘制直方图的列。如果未指定,则默认绘制所有数值列的直方图。 -
by: 字符串或字符串列表,可选。用于指定分组变量,以便为每个组绘制直方图。 -
grid: 布尔值,默认为 True。是否在直方图上显示网格线。 -
xlabelsize: 整数,可选。用于设置 x 轴标签的大小。 -
xrot: 浮点数,可选。用于设置 x 轴标签的旋转角度。 -
ylabelsize: 整数,可选。用于设置 y 轴标签的大小。 -
yrot: 浮点数,可选。用于设置 y 轴标签的旋转角度。 -
ax: Matplotlib axes 对象或数组,可选。如果提供,则在指定的 axes 对象上绘制直方图。 -
sharex: 布尔值,默认为 False。如果为 True,并且绘制多个直方图,则所有直方图共享相同的 x轴。 -
sharey: 布尔值,默认为 False。如果为 True,并且绘制多个直方图,则所有直方图共享相同的 y轴。 -
figsize: 元组(宽度,高度),可选。用于设置整个图形的大小。 -
layout: 元组(行数,列数),可选。用于指定直方图的布局。 -
bins: 整数或序列,默认为 10。用于设置直方图的柱子数量或边界。 -
backend: 字符串,可选。用于指定绘图的后端。默认情况下,Pandas 使用 Matplotlib。 -
legend: 布尔值,默认为 False。如果为 True,并且指定了by参数,则在直方图上显示图例。 -
**kwargs: 关键字参数,这些参数会被传递给 Matplotlib 的hist函数,用于进一步自定义直方图。
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
# 创建一个包含正态分布数据的 DataFrame
df = pd.DataFrame(np.random.randn(100, 3), columns=['A', 'B', 'C'])
# 绘制 A 列的直方图,设置 20 个柱子,并指定图形大小
df['A'].hist(bins=20, figsize=(8, 4))
# 绘制所有列的直方图,每个直方图在不同的子图中
df.hist(figsize=(10, 7), bins=30)
# 使用 by 参数按列 B 的值分组绘制列 A 的直方图
df.hist(column='A', by='B', bins=15, figsize=(10, 5))
# 使用 tight_layout 自动调整子图布局
fig.tight_layout()
# 显示图像
plt.show()



8. 其他常用方法
(1)nunique
用于计算 DataFrame 中唯一值的数量
DataFrame.nunique(axis=0, dropna=True)
-
axis=0:默认值,表示按列进行操作。如果设置为axis=1,则表示按行进行操作。 -
dropna=True:默认值,表示在计算唯一值之前先排除掉缺失值(NaN)。如果设置为False,则缺失值也会被计算在内。
import pandas as pd
import numpy as np
# 创建一个DataFrame
df = pd.DataFrame({
'A': [1, 2, 2, 3, 3, 3],
'B': ['a', 'b', 'b', 'c', 'c', 'c'],
'C': [np.nan, np.nan, 1, 2, 2, 2]
})
# 使用nunique()方法计算每列的唯一值数量
unique_counts = df.nunique(axis=0, dropna=True)
print(unique_counts)
(2)value_counts
用于计算 DataFrame 中各个值出现的频率的一个方法
DataFrame.value_counts(subset=None, normalize=False, sort=True, ascending=False, dropna=True)
-
subset=None:可选参数,用于指定要进行计算操作的列名列表。如果未指定,则对整个DataFrame的所有列进行操作 -
normalize=False:布尔值,默认为False。如果设置为True,则返回每个值的相对频率,而不是计数 -
sort=True:布尔值,默认为True。如果设置为True,则结果将按计数值降序排序 -
ascending=False:布尔值,默认为False。当sort=True时,此参数指定排序顺序。如果设置为True,则结果将按计数值升序排序 -
dropna=True:布尔值,默认为True。如果设置为True,则在计数之前排除缺失值
import pandas as pd
import numpy as np
# 创建一个DataFrame
df = pd.DataFrame({
'A': [1, 2, 2, 3, 3, 3],
'B': ['a', 'b', 'b', 'c', 'c', 'c'],
'C': [np.nan, np.nan, 1, 2, 2, 2]
})
# 使用value_counts()方法计算值的频率
# 计算 A、B 列,计数,排序,降序,计数前排除空值
value_counts = df.value_counts(subset=['A', 'B'], normalize=False, sort=True, ascending=False, dropna=True)
print(value_counts)
(3)describe
用于生成 DataFrame 中数值列的统计摘要,会返回一个 DataFrame,其中包含以下统计信息:
-
count:非NA值的数量 -
mean:平均值 -
std:标准差 -
min:最小值 -
分位数:可指定 -
max:最大值
DataFrame.describe(percentiles=None, include=None, exclude=None)
-
percentiles=None:一个列表形式的数值,用于指定要计算的分位数。默认情况下,会计算25%,50%,和75%这三个分位数。如果你想要不同的分位数,可以在这里指定。 -
include=None:一个列表形式的字符串或字符串序列,用于指定要包含在描述统计中的数据类型。默认情况下,只包括数值类型的数据。 -
exclude=None:一个列表形式的字符串或字符串序列,用于指定要从描述统计中排除的数据类型。
Pandas 3 中,字符串类型处理规则发生了变化,
exclude=['object']以前会兼容性地排除str类型,但该行为现已弃用,因此触发警告;由于include=['number']已限定只统计数值列,可以直接删除exclude=['object']。
import pandas as pd
# 创建一个DataFrame
df = pd.DataFrame({
'A': [1, 2, 2, 3, 3, 3],
'B': [10, 20, 20, 30, 30, 30],
'C': ['foo', 'bar', 'bar', 'baz', 'baz', 'baz']
})
# 使用describe()方法生成统计摘要
# description = df.describe(percentiles=[0.5, 0.75, 0.9], include=['number'], exclude=['object'])
description = df.describe(percentiles=[0.5, 0.75, 0.9], include=['number'])
print(description)
(4)copy
用于创建DataFrame 的一个副本
DataFrame.copy(deep=True)
deep=True:默认为True,表示创建一个深拷贝。- 在深拷贝中,DataFrame 中的所有数据都会被复制到新的DataFrame 中,因此原始 DataFrame 中的数据与副本 DataFrame 中的数据是完全独立的
- 如果你对副本进行修改,原始 DataFrame 不会受到影响,反之亦然
Pandas 3 中:
df.copy():创建深拷贝,修改副本不会影响原数据。df.copy(deep=False):创建浅拷贝,在 Pandas 3 的写时复制机制下,修改副本也不会影响原数据。Pandas 3 默认采用 Copy-on-Write(写时复制)机制,
df['A'][0] = 999这类链式赋值在旧版本中可能通过视图修改原数据,但在新版本中中间对象会被视为独立副本,无法可靠地更新原 DataFrame,因此应使用df.loc[0, 'A'] = 999一步完成赋值,避免ChainedAssignmentError
import pandas as pd
# 创建一个 DataFrame
df = pd.DataFrame({
'A': [1, 2, 3],
'B': [4, 5, 6]
})
# 创建深拷贝
df_deep_copy = df.copy()
# 创建浅拷贝
df_shallow_copy = df.copy(deep=False)
# 修改深拷贝中的数据
# df_deep_copy['A'][0] = 999
df_deep_copy.loc[0,'A'] = 999
# 修改浅拷贝中的数据
# df_shallow_copy['B'][0] = 888
df_shallow_copy.loc[0,'B'] = 888
# 打印原始DataFrame和副本
print("Original DataFrame:")
print(df)
print("\nDeep Copy:")
print(df_deep_copy)
print("\nShallow Copy:")
print(df_shallow_copy)
运行结果:
Original DataFrame:
A B
0 1 4
1 2 5
2 3 6
Deep Copy:
A B
0 999 4
1 2 5
2 3 6
Shallow Copy:
A B
0 1 888
1 2 5
2 3 6
(5)reset_index
用于重置DataFrame 的索引
将原来的行索引恢复为默认的整数索引(从 0 开始),原索引可以选择保留为普通列或直接丢弃
DataFrame.reset_index(level=None, *, drop=False, inplace=False, col_level=0, col_fill='', allow_duplicates=_NoDefault.no_default, names=None)
-
level=None:整数或索引名称,用于指定要重置的索引级别。对于多级索引的DataFrame,可以指定一个级别或级别列表。如果为None,则重置所有级别。 -
drop=False:布尔值,默认为False。如果为True,则重置索引后,原始索引将不会作为列添加到DataFrame 中。如果为False,则原始索引将作为新列添加到DataFrame 中。 -
inplace=False:布尔值,默认为False。如果为True,则直接在原始DataFrame 上进行操作,不返回新的DataFrame。 -
col_level=0:如果原始索引是多级索引,则指定新列的索引级别。 -
col_fill='':如果原始索引是多级索引,并且col_level比原始索引的级别多,则使用此值填充缺失的级别。 -
allow_duplicates=_NoDefault.no_default:允许索引列中出现重复值。如果设置为False,则在尝试插入重复列时会引发ValueError。 -
names=None:列表或元组,用于为新列指定名称。默认情况下,如果drop为False,则使用原始索引的名称。
import pandas as pd
# 创建两个列表,它们将用作多级索引的级别
arrays = [['Falcon', 'Falcon', 'Parrot', 'Parrot'], # 第一级索引的值
['Captive', 'Wild', 'Captive', 'Wild']] # 第二级索引的值
# 使用 arrays 列表创建一个 DataFrame,'Max Speed' 列包含对应于多级索引的数据
df = pd.DataFrame({'Max Speed': [390., 350., 30., 20.]}, # 数据
index=arrays) # 使用arrays列表作为多级索引
print("原始的:")
print(df)
# 重置所有索引级别,并将它们作为列添加到 DataFrame 中
print("\n重置的:")
df_reset = df.reset_index()
print(df_reset)
# 只重置第二级索引,并将它作为列添加到 DataFrame中
print("\n只重置第二级索引")
df_reset_level_1 = df.reset_index(level=1)
print(df_reset_level_1)
# 重置所有索引级别,但不将它们作为列添加到 DataFrame中
print("\n重置所有索引,但是不保存:")
df_reset_drop = df.reset_index(drop=True)
print(df_reset_drop)
运行结果:
原始的:
Max Speed
Falcon Captive 390.0
Wild 350.0
Parrot Captive 30.0
Wild 20.0
重置的:
level_0 level_1 Max Speed
0 Falcon Captive 390.0
1 Falcon Wild 350.0
2 Parrot Captive 30.0
3 Parrot Wild 20.0
只重置第二级索引
level_1 Max Speed
Falcon Captive 390.0
Falcon Wild 350.0
Parrot Captive 30.0
Parrot Wild 20.0
重置所有索引,但是不保存:
Max Speed
0 390.0
1 350.0
2 30.0
3 20.0
(6)info
用于显示DataFrame 的概要信息的一个便捷方法,它提供了关于 DataFrame 的列、非空值数量、数据类型以及内存使用情况的信息。
DataFrame.info(verbose=None, buf=None, max_cols=None, memory_usage=None, show_counts=None)
-
verbose=None:控制输出信息的详细程度。 -
buf=None:一个打开的文件对象或类似文件的对象。如果提供,则输出将被写入这个缓冲区而不是标准输出。 -
max_cols=None:要显示的最大列数。如果DataFrame 的列数超过这个值,则只会显示部分列的信息。 -
memory_usage=None:控制是否显示内存使用情况。可以设置为True或False,或者是一个字符串,'deep’表示深度计算内存使用情况,考虑对象内部数据。 -
show_counts=None:控制是否显示非空值的数量。如果设置为True,则会在每个列旁边显示非空值的数量。
import pandas as pd
# 创建一个DataFrame
df = pd.DataFrame({
'A': [1, 2, 3, None],
'B': ['a', 'b', 'c', 'd'],
'C': [1.1, 2.2, 3.3, 4.4]
})
# 显示DataFrame的概要信息
df.info(verbose=True, memory_usage='deep', show_counts=True)
运行结果:
RangeIndex: 4 entries, 0 to 3
Data columns (total 3 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 A 3 non-null float64
1 B 4 non-null str
2 C 4 non-null float64
dtypes: float64(2), str(1)
memory usage: 396.0 bytes
(7)apply
允许你对DataFrame 中的每个元素、行或列应用一个函数。
DataFrame.apply(func, axis=0, raw=False, result_type=None, args=(), **kwargs)
-
func:函数,应用于每个元素、行或列。这个函数需要你自定义,或者使用内置的函数。 -
axis=0:指定应用函数的轴。 -
raw=False:布尔值,默认为False,则每行或每列将作为Series使用,如果为True,则将作为Ndarray数组,性能会更好。 -
result_type=None:控制返回类型。可以是以下之一:-
‘reduce’:如果可能的话,如果应用函数返回一个列表,这个列表会被转换成一个 Series。
-
‘broadcast’:结果会被广播到原始 DataFrame 的形状,保留原始的索引和列。
-
‘expand’:如果应用函数返回一个列表(或类似列表的结构),则这个列表会被转换为多个列。这意味着每个列表元素都会变成 DataFrame 的一列。
-
-
args=():元组,包含传递给函数的位置参数。 -
**kwargs:关键字参数,将被传递给函数。
import pandas as pd
# 创建一个DataFrame
df = pd.DataFrame({
'A': [1, 2, 3],
'B': [4, 5, 6],
'C': [7, 8, 9]
})
print(df)
# 定义一个函数,计算每行的平均值
def mean_row(row):
return row.mean()
# 应用函数到每行
result = df.apply(mean_row, axis=1)
print(result)
运行结果:
A B C
0 1 4 7
1 2 5 8
2 3 6 9
0 4.0
1 5.0
2 6.0
dtype: float64
(四)保存与读取
1. to_csv
用于将DataFrame 对象保存为CSV(逗号分隔值)文件的方法
DataFrame.to_csv(path_or_buf=None, sep=',', na_rep='', float_format=None, columns=None, header=True, index=True, mode='w', encoding=None, quoting=None, quotechar='"', **kwargs)
-
path_or_buf: 指定输出文件的路径或文件对象。 -
sep: 字段分隔符,通常使用逗号,或制表符\t。 -
na_rep: 缺失值的表示方式,默认为空字符串''。 -
float_format: 浮点数的格式化方式,例如'%.2f'用于格式化为两位小数。 -
columns: 要写入的列的子集,默认为None,表示写入所有列。 -
header: 是否写入列名,通常设置为True。 -
index: 是否写入行索引,通常设置为True或False,取决于是否需要索引。 -
mode: 写入模式,通常使用’w’(写入,覆盖原文件)或’a’(追加到文件末尾)。 -
encoding: 文件编码,特别是在处理非ASCII 字符时很重要 -
quoting: 控制字段引用的行为,通常用于确保字段中的分隔符被正确处理。 -
quotechar: 用于包围字段的字符,默认为双引号"。 -
**kwargs: 其他关键字参数。
import pandas as pd
# 创建一个简单的DataFrame
data = {
'姓名' : ['张三' , '李四' , '王五' ],
'年龄' : [28, 34, 29],
'城市' : ['北京' , '上海' , '广州' ]
}
df = pd.DataFrame(data)
# 将DataFrame保存为CSV文件
df.to_csv('人员信息.csv' , index=False, encoding='utf_8_sig')

2. to_excel
在操作excel表格之前,需要安装一个库: openpyxl,因为 pandas 库本身并不包含写入Excel文件的直接支持,如果没有安装的话将无法操作excel。
pip install openpyxl
Pandas中的 to_excel 用于将 DataFrame 保存为 Excel文件。
DataFrame.to_excel(excel_writer, sheet_name='Sheet1', na_rep='', float_format=None, columns=None, header=True, index=True, index_label=None, startrow=0, startcol=0, engine=None, merge_cells=True, inf_rep='inf', freeze_panes=None, storage_options=None)
-
excel_writer:字符串或ExcelWriter对象,指定输出文件的路径或文件对象。 -
sheet_name='Sheet1':要写入的工作表名称。 -
na_rep='':指定缺失值的表示方式。 -
float_format=None:浮点数的格式化方式,例如’%.2f’。 -
columns=None:要写入的列的子集,默认为None,表示写入所有列。 -
header=True:是否写入列名,默认为True。 -
index=True:是否写入行索引,默认为True。 -
index_label=None:指定行索引列的列名,如果为None,并且header为True,则使用索引名。 -
startrow=0:写入DataFrame 的起始行位置,默认为0。 -
startcol=0:写入DataFrame 的起始列位置,默认为0。 -
engine=None:指定用于写入文件的引擎,可以是’openpyxl’ (默认)或’xlsxwriter’。 -
merge_cells=True:是否合并单元格,这在有合并单元格的Header时很有用。 -
inf_rep='inf':指定无限大的表示方式。 -
freeze_panes=None:指定冻结窗口的单元格范围,例如’A2’。 -
storage_options=None:指定存储连接的参数,例如认证凭据。
import pandas as pd
# 创建一个简单的DataFrame
data = {
'姓名' : ['张三' , '李四' , '王五' ],
'年龄' : [28, 34, 29],
'城市' : ['北京' , '上海' , '广州' ]
}
df = pd.DataFrame(data)
# 将DataFrame保存为Excel文件
df.to_excel('人员信息.xlsx' , index=False)

3. read_csv
pandas.read_csv 是一个非常强大的函数,用于从文件、URL、文件-like对象等读取逗号分隔值(CSV)文件。这个函数有很多参数,允许你以多种方式自定义数据加载过程。
pandas.read_csv(filepath_or_buffer, sep, header, usercols, na_values, parse_dates, skiprows, nrows)
-
filepath_or_buffer:指定要读取的 CSV 文件的路径或文件对象。可以是一个字符串,表示文件的绝对路径或相对路径;也可以是一个已经打开的文件对象(例如通过open()函数打开的文件)。 -
sep: 字符串,用于分隔字段的字符。默认是逗号,,但可以是任何字符,例如';'或'\t'(制表符)。 -
header: 整数或整数列表,用于指定行号作为列名,或者没有列名(例如header=None)。默认为'infer',表示自动检测列名。 -
usecols: 列表或 callable,用于指定要读取的列。可以是列名的列表,也可以是列号的列表。 -
na_values: 字符串、列表或字典,用于指定哪些其他值应该被视为NA/NaN。 -
parse_dates: 列表或字典,用于指定将哪些列解析为日期。 -
skiprows: 整数或列表,用于指定要跳过的行号或条件。 -
nrows: 整数,用于指定要读取的行数。
import pandas as pd
c = pd.read_csv("人员信息.csv")
print(c)
4. read_excel
pandas.read_excel 是pandas库中用于读取Excel文件( .xls 或 .xlsx)的函数。它可以将Excel文件中的数据读取为DataFrame 对象,便于进行数据分析和处理。
pandas.read_excel(io, sheet_name=0, header=0, index_col=None, usecols=None, squeeze=False, dtype=None, skiprows=None, nrows=None, na_values=None, keep_default_na=True, parse_dates=False, date_parser=None, skipfooter=0, convert_float=True, **kwds)
-
io: 文件路径或文件对象。这是唯一必需的参数,用于指定要读取的Excel文件。 -
sheet_name=0: 要读取的表名或表的索引号。默认为0,表示读取第一个工作表。可以指定工作表名或索引号,如果指定多个,将返回一个字典,键为工作表名,值为对应的DataFrame。 -
header=0: 用作列名的行号,默认为0,即第一行作为列名。如果没有标题行,可以设置为None。 -
index_col=None: 用作行索引的列号或列名。默认为None,表示不使用任何列作为索引。可以是一个整数、字符串或列名的列表。 -
usecols=None: 要读取的列。默认为None,表示读取所有列。可以是一个整数列表、字符串列表或Excel列的位置(如[0, 1, 2])或字母标记(如['A', 'B', 'C'])。 -
squeeze=False: 如果读取的数据只有一列,当设置为True时,返回一个Series而不是DataFrame。 -
dtype=None: 指定某列的数据类型。默认为None,表示自动推断。可以是一个字典,键为列名,值为NumPy数据类型。 -
skiprows=None: 要跳过的行号或行号列表。默认为None,表示不跳过任何行。可以是整数或整数列表。 -
nrows=None: 读取的行数,从文件头开始。默认为None,表示读取所有行。 -
na_values=None: 将指定的值替换为NaN。默认为None,表示不替换。可以是一个值或值的列表。 -
keep_default_na=True: 如果为True(默认),则除了通过na_values指定的值外,还将默认的NaN值视为NaN。 -
parse_dates=False: 是否尝试将列解析为日期。默认为False。可以是一个布尔值、列名列表或列号的列表。 -
date_parser=None: 用于解析日期的函数。默认为None,表示使用pandas默认的日期解析器。 -
skipfooter=0: 要跳过的文件底部的行数。默认为0,表示不跳过任何底部的行。 -
convert_float=True: 是否将所有浮点数转换为64位浮点数。默认为True,以避免数据类型推断问题。 -
**kwds: 允许用户传递其他关键字参数,这些参数可能会被引擎特定的读取器所识别。
import pandas as pd
x = pd.read_excel("人员信息.xlsx")
print(x)
原文地址: https://www.cveoy.top/t/topic/qHR2 著作权归作者所有。请勿转载和采集!