Python之Pandas
Pandas
Pandas是Python中最流行的数据处理和分析库之一,它提供了高效的数据结构和数据分析工具。Pandas 主要有两种数据结构:一维数组Series和二维表格数据结构DataFrame。
1. 创建 Pandas 数据结构
Series
Series 是一种类似于一维数组的对象,包含一组数据(可以是任何数据类型),并且可以关联一个索引(index)。基本语法:
pandas.Series(data, index=None, dtype=None, name=None, copy=False)
参数 | |
---|---|
data | 输入的数据,可以是列表、元组、字典、NumPy 数组等。 |
index | 指定索引标签。如果未提供,默认使用整数索引(0, 1, 2, …)。可以传入一个列表或数组,长度需要与数据相同。 |
dtype | 指定输出系列的数据类型,如 ‘float64’, ‘int32’, ‘object’ 等。如果不指定,Pandas 会自动推断数据类型。 |
name | 指定Series 的名称,会显示在输出中。 |
copy | 表示是否复制数据,默认值为 False。 |
返回值 | Pandas的Series 对象。 |
使用示例:
import pandas as pd
import numpy as np# 从列表创建,指定索引和名称
s1 = pd.Series([10, 20, 30], index=['x', 'y', 'z'], name='my_series', dtype='float64')# 从字典创建(字典键自动成为索引)
s2 = pd.Series({'a': 1, 'b': 2, 'c': 3})# NumPy 数组
s3 = pd.Series(np.arange(1,6))# 通过标量创建
s4 = pd.Series(100,index=range(5))
DataFrame
DataFrame 是一种二维异构的表格数据结构,可以看作是一个表格(既有行标签 index ,又有列标签 columns)。DataFrame 由多个 Series 组成。基本语法:
pandas.DataFrame(data=None, index=None, columns=None, dtype=None, copy=False)
参数 | |
---|---|
data | 输入的数据,可以是ndarray、字典、列表、Series、标量或另一个DataFrame |
index | 行标签,如果没有传递 index 值,则默认行标签是 RangeIndex(0, 1, 2, …,n),n 代表 data 的元素个数。 |
columns | 列标签,如果没有传递 columns 值,则默认列标签是 RangeIndex(0, 1,2, …, n)。 |
dtype | 指定数据类型,只允许使用一种数据类型。如果未指定,Pandas 会根据数据自动推断数据类型。 |
copy | 表示是否复制数据,默认值为 False。 |
返回值 | Pandas的DataFrame对象。 |
使用示例:
import pandas as pd
import numpy as np# 从字典创建 DataFrame,字典的键作为列名,值作为列的数据
data = {'Name': ['Alice', 'Bob', 'Charlie'], 'Age': [24, 27, 22]}
df1 = pd.DataFrame(data, index=['a', 'b', 'c'])# 从二维数组创建
df2 = pd.DataFrame(np.random.rand(3, 2), columns=['col1', 'col2'], index=['a', 'b', 'c'])# 从列表的列表创建,列表中每个元素代表一行数据
df3 = pd.DataFrame([[1, 'a'], [2, 'b'], [3, 'c']], columns=['num', 'char'])
df4 = pd.DataFrame([1,2,3,4,5], columns=['num'])
df5 = pd.DataFrame([{'a': 1, 'b': 2},{'a': 5, 'b': 10, 'c': 20}], index=['first', 'second']) # 列表中每个字典代表一行数据,字典的键是列标签# 从Series字典创建,可以对不同列设置自定义数据类型
df6 = pd.DataFrame({
"Name":pd.Series(['xiaowang', 'Lily', 'Anne']),
"Age":pd.Series([20, 30, 40], dtype=float),
"gender":pd.Series(["男", "男", "女"]),
"salary":pd.Series([5000, 8000, 10000], dtype=float)
})
2. 常用属性
import pandas as pd
s = pd.Series([1, 2, 3])
df = pd.DataFrame({'A': [1, 2], 'B': [3.5, 4.5]})
属性 | | |
---|---|---|
values | s.values :以 numpy 数组的形式返回 Series 中的值。 | df.values :以 numpy 数组的形式返回 DataFrame 中的值。 |
dtypes | s.dtypes :返回 Series 的数据类型。 | df.dtypes :返回 DataFrame 中各列的类型。 |
shape | s.shape :返回 Series 的维度(一个元组)。总是返回 (n,) 形式的元组,其中 n 是数据的长度。 | df.shape :返回 DataFrame 的维度(行数, 列数)。 |
size | s.size :返回 Series 的元素数量。 | df.size :返回 DataFrame 的元素总数(行数 * 列数)。 |
empty | s.empty :判断 Series 是否为空。如果 Series 没有数据,则返回 True,否则返回 False。 | df.empty :判断 DataFrame 是否为空。如果 DataFrame 没有数据,则返回 True,否则返回 False。 |
ndim | s.ndim :返回 Series 的维度数,定值恒为1。 | df.ndim :返回 DataFrame 的维度数。通常,DataFrame 的 ndim 值为 2。 |
axes | s.axes :返回行索引的列表。 | df.axes :返回一个包含行和列索引的列表。对于 DataFrame,通常返回 [行索引, 列索引]。 |
T | s.T :返回 Series 的转置,就是 Series 本身。 | df.T :返回 DataFrame 的转置(行列互换)。 |
name | s.name :返回 Series 的名称。 | df.name :返回 DataFrame 的名称。 |
index | s.index :返回 Series 的索引对象。 | df.index :返回 DataFrame 的行索引。 |
columns | | df.columns :返回 DataFrame 的列标签。 |
3. 索引操作
修改索引名 – 直接赋值索引属性值/rename()
在 pandas 中,修改 Series 或 DataFrame 行列名有如下常用的方式:
- 直接赋值索引属性值
直接通过给 Series 或 DataFrame 的 index 和 columns 属性赋值来修改行索引和列标签。这种方法可以直接修改行列名。使用示例:
import pandas as pd# 创建一个 Series
s = pd.Series([1, 2, 3], index=['A', 'B', 'C'])
# 修改索引
s.index = ['X', 'Y', 'Z']# 创建一个 DataFrame
df = pd.DataFrame({'A': [1, 2, 3],'B': [4, 5, 6]
})
# 直接修改列名
df.columns = ['X', 'Y']
# 直接修改行名
df.index = ['a', 'b', 'c']
- rename()
rename() 是 Pandas 中用于重命名轴标签(行索引或列名)的重要方法,可以对 DataFrame 或 Series 的索引和列名进行灵活的修改。基本语法:
DataFrame.rename(mapper=None, axis=None, columns=None, index=None, inplace=False, level=None, errors='raise')
参数 | |
---|---|
mapper | 此参数可以用于行或列标签的重命名,可以是字典、函数、列表/数组(需与长度匹配)。 ● 如果传递的是字典,它的键值对应该是原始标签到新标签的映射关系。 ● 如果传递的是函数,函数会应用到每个标签上,并返回新标签。 ● 如果为 None,会使用 columns 或 index 参数。 |
axis | 用来指定操作的轴,如果指定了 columns 或 index,则不需要显式使用 axis,它会自动根据上下文选择。 ● 0 或 ‘index’ :重命名行索引。 ● 1 或 ‘columns’ :重命名列标签。 Series无此参数。 |
columns | 此参数可以用于行或列标签的重命名,可以是字典、函数、列表/数组(需与长度匹配)。 ● 如果 axis 为 1 或 ‘columns’,则可以用此参数。 ● 如果传递了 mapper,此参数会被忽略。 Series无此参数。 |
index | 此参数可以用于行或列标签的重命名,可以是字典、函数、列表/数组(需与长度匹配)。 ● 如果 axis 为 0 或 ‘index’,则可以用此参数。 ● 如果传递了 mapper,此参数会被忽略。 |
inplace | 是否原地修改对象,默认值False。 ● 如果设置为 True,则在原地修改 DataFrame,不返回新的 DataFrame。 ● 如果为 False,则返回一个新的 DataFrame 或 Series。 |
level | 多级索引中指定要重命名的层级。 |
errors | 指定如果出现无效的列或索引名时如何处理。 ● ‘raise’(默认值):会抛出错误。 ● ‘ignore’:忽略错误,不会抛出异常。 |
返回值 | 根据inplace值返回对应DataFrame。 |
使用示例
import pandas as pd
# 重命名Series索引
s = pd.Series([1, 2], index=['A', 'B'])
# 使用index参数
s.rename({'A': 'a', 'B': 'b'})
# 使用函数转换
s.rename(lambda x: x.lower())# 重命名DataFrame索引
df = pd.DataFrame({'A': [1, 2], 'B': [3, 4]})
# 使用columns参数
df.rename(columns={'A': 'a', 'B': 'b'})
# 使用mapper+axis
df.rename({'A': 'a', 'B': 'b'}, axis=1)
# 使用函数转换
df.rename(columns=lambda x: x.lower())
df.rename(index=lambda x: f"row_{x+1}")
# 使用index参数
df.rename(index={0: 'row1', 1: 'row2'})
重置索引 – reindex()
pandas的reindex函数用于对DataFrame或Series的索引进行重置操作。该函数可以根据新的索引对数据进行重排或填充缺失值。基本语法:
Series.reindex(index=None, method=None, copy=True, level=None, fill_value=nan, limit=None, tolerance=None)
DataFrame.reindex(labels=None, index=None, columns=None, axis=None, method=None, copy=True, level=None, fill_value=nan, limit=None, tolerance=None)
参数 | |
---|---|
labels | 新标签/索引使“ axis”指定的轴与之一致。 |
index | 用于指定新的索引标签。 |
columns | 用于指定新的列标签,仅对 DataFrame 有效。 |
axis | 指定应用轴。 ● 0 或 ‘index’:行; ● 1 或 ‘columns’:列。 |
method | 填充缺失值的方法。 ● ‘ffill’(前向填充):用前一个有效值填充缺失值。 ● ‘bfill’(后向填充):用后一个有效值填充缺失值。 |
copy | 是否返回副本。 ● 如果为 True,则返回新的对象; ● 如果为 False,则返回原始对象。 |
level | 当使用多级索引(MultiIndex)时,指定要重新索引的级别。 |
fill_value | 用于填充缺失数据(默认是 NaN)。如果新的索引包含不存在于原索引中的标签,则会填充此值。 |
limit | 该参数指定填充的最大数量。如果某些索引标签没有对应的数据,limit 限制了填充的次数。 |
tolerance | 匹配容差。不精确匹配的原始标签和新标签之间的最大距离。 |
返回值 | 根据copy值返回对应DataFrame。 |
使用示例:
import pandas as pds = pd.Series([10, 20, 30], index=['a', 'b', 'c'])
# 重新索引(包含新索引'd')
new_s = s.reindex(['a', 'b', 'c', 'd'])df = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6]}, index=['x', 'y', 'z'])
# 重索引行
df.reindex(['y', 'x', 'z', 'w'])
# 重索引列
df.reindex(columns=['B', 'A', 'C'])
# 同时重索引行和列
df.reindex(index=['x', 'y', 'w'], columns=['A', 'C'])
4. 索引和切片
在 pandas 中,索引和切片是操作 Series 和 DataFrame 数据的核心概念,通过索引和切片可以访问、修改和处理数据。
位置索引和切片 .iloc
位置索引是基于 Series 或 DataFrame 中元素的位置,类似于 Python 中的列表或 numpy 数组,使用整数索引从 0 开始。标准形式如:数据结构.iloc[start,stop]
。
- start:行位置。可以是单个整数、整数列表或切片,分别对应单元素索引、整数列表索引、切片索引。
- stop:列位置。可以是单个整数、整数列表或切片,分别对应单元素索引、整数列表索引、切片索引。Series 不包含此参数。
数据结构 | | | |
---|---|---|---|
Series | Series 可以通过整数位置索引访问元素,位置索引是从 0 开始的。 方式①: Series[seq] 。方式②: Series.iloc[seq] (通常0 ≤ seq < Series.size,但Series的index 非默认 时支持负数索引,负数表示从序列的末尾开始倒数。) | Series 可以通过 整数列表索引 来选择多个元素,这些整数索引表示 Series 中元素的位置。 方式①: Series[[0,1,2,...]] 方式②: Series.iloc[[0,1,2,...]] 返回值:返回一个新的 Series。 | 方式①:series[start:stop:step] 方式②: series.iloc[start:stop:step] ● start:切片的起始位置。默认为0。 ● stop:切片的结束位置(不包含此位置)。默认为数组的长度。 ● step:步长,默认为1。 ● 返回值:返回一个新的 Series。 |
DataFrame | DataFrame 使用 iloc 进行基于整数位置的行列索引和切片,行列索引都是从 0 开始的。 基本语法: DataFrame.iloc[row, col] (通常0 ≤ row < len(DataFrame.index),0≤ col < len(DataFrame.columns),但DataFrame的index或columns 非默认 时支持负数索引,负数表示从序列的末尾开始倒数。) | DataFrame 也支持通过 整数列表索引 来选择特定的行或列,整数列表索引可以基于位置提取数据。基本语法:DataFrame.iloc[[0,1,2,...],[0,1,2,...]] (行整数列表和列整数列表长度不要求相等) 返回值:返回一个新的 DataFrame。 | 基本语法:DataFrame.iloc[start_row:end_row:row_step, start_col:end_col:col_step] ● start_row:行切片开始的位置(包含),默认为0。 ● end_row:行切片结束的位置(不包含), 默认为数组的长度。 ● row_step:行切片的步长,默认为1。 ● start_col:列切片开始的位置(包含),默认为0。 ● end_col:列切片结束的位置(不包含), 默认为数组的长度。 ● col_step:列切片的步长,默认为1。 ● 返回值:返回一个新的Series 或 DataFrame。 |
使用示例:
import pandas as pd# Series
s = pd.Series([10, 20, 30, 40, 50], index=['a', 'b', 'c', 'd', 'e'])
# 访问第一个元素
print(s[0]) # 输出: 10
# 访问最后一个元素
print(s[-1]) # 输出: 50
# 使用整数位置索引选择多个元素
print(s[[0, 2, 4]])
# 基于位置的切片
print(s[1:4]) # 输出: b 20, c 30, d 40# DataFrame
df = pd.DataFrame({'A': [1, 2, 3, 4],'B': [5, 6, 7, 8],'C': [9, 10, 11, 12]
})
# 选择第一行和第一列的交集
print(df.iloc[0, 0])
# 使用整数列表索引选择特定的行和列
print(df.iloc[[1, 3], [0, 1]])
# 选择第一行
print(df.iloc[0])
# 选择第一列
print(df.iloc[:, 0])
# 选择多个行和列
print(df.iloc[1:3, 0:2]) # 输出第二到第三行,第一到第二列
标签索引和切片 .loc
在 pandas 中,标签索引根据行和列的标签进行定位。标准形式如:数据结构.loc[row_label, column_label]
。
- row_label:行标签,可以是单个标签、标签列表或标签的切片,分别对应单元素索引、标签列表索引、切片索引。
- column_label:列标签,同样可以是单个标签、标签列表或标签的切片,分别对应单元素索引、标签列表索引、切片索引。Series 不包含此参数。
数据结构 | | | |
---|---|---|---|
Series | 通过标签(index)来访问 Series 中的元素。 方式①: Series[label] 。方式②: Series.loc[label] | 可以通过标签列表来选择 Series 中多个元素。它类似于用单个标签选择数据,只是这里用的是多个标签。 方式①: Series[[label_1,label_2,label_3,...]] 方式②: Series.loc[[label_1,label_2,label_3,...]] 返回值:返回一个新的 Series。 | 方式①:series[start_label:end_label:step] 方式②: series.loc[start_label:end_label:step] ● start_label:开始标签。 ● end_label:结束标签(包含此位置)。 ● step:步长,决定每隔多少个元素选择一个。 ● 返回值:返回一个新的 Series。 |
DataFrame | loc 用于基于标签的行列索引和索引。 基本语法: DataFrame.loc[row, col] | DataFrame可以通过标签列表来选择特定的行或列数据。基本语法:DataFrame.loc[[rowlabel_1,rowlabel_2,rowlabel_3,...],[collabel_1,collabel_2,collabel_3,...]] (行标签列表和列标签列表长度不要求相等,且可只选定其中一个标签列表) 返回值:返回一个新的 DataFrame。 | 基本语法:DataFrame.loc[start_rowlabel:end_rowlabel:row_step, start_collabel:end_collabel:col_step] ● start_rowlabel:开始行标签(包含),默认为起始行标签。 ● end_rowlabel:结束行标签(包含),默认为末尾行标签。 ● row_step:行标签的步长,默认为1。 ● start_collabel:开始列标签(包含),默认为起始列标签。 ● end_collabel:结束列标签(包含),默认为末尾列标签。 ● col_step:列标签的步长,默认为1。 ● 返回值:返回一个新的Series 或 DataFrame。 |
使用示例:
import pandas as pd# Series
s = pd.Series([10, 20, 30, 40, 50], index=['a', 'b', 'c', 'd', 'e'])
# 通过标签访问元素
print(s['a']) # 输出: 10
# 使用标签列表选择数据
print(s[['a', 'c', 'e']])
# 基于标签的切片
print(s['b':'d']) # 输出: b 20, c 30, d 40# DataFrame
df = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6]}, index=['x', 'y', 'z'])
# 获取单元素
df.loc['x', 'A'] # 返回标量值1
# 获取列
df['A'] # 返回列A的Series
df[['A']] # 返回只包含列A的DataFrame
# 使用行标签列表和列标签列表选择特定的行和列
print(df.loc['x':'z', ['A', 'B']])
df.loc['x':'y', 'A':'B'] # 切片(包含末端)
布尔索引
在 pandas 中,布尔索引 是一种通过布尔条件来选择 DataFrame 或 Series 中数据的方式。通过布尔索引可以根据满足特定条件的数据进行筛选,从而快速提取所需的数据。
使用示例:
import pandas as pd# 创建一个 Series
s = pd.Series([10, 20, 30, 40, 50])
# 条件:选择大于 30 的元素
filtered_s = s[s > 30]
print(filtered_s)# 创建一个 DataFrame
data = {'A': [1, 2, 3, 4, 5], 'B': [10, 20, 30, 40, 50]}
df = pd.DataFrame(data)
# 条件:选择 'A' 列大于 2 的行
filtered_df = df[df['A'] > 2]
# 使用多个条件筛选:选择 'A' 列大于 2 且 'B' 列小于 40 的行
filtered_df = df[(df['A'] > 2) & (df['B'] < 40)]
print(filtered_df)
5. 查看基本信息
import pandas as pd
s = pd.Series([1, 2, 3, 4, 5])
df = pd.DataFrame({'A': [1, 2, 3, 4, 5], 'B': [10, 20, 30, 40, 50]})
方法 | | | |
---|---|---|---|
head(n) | 返回前 n 行。 n为可选参数,默认为5。 | s.head() s.head(3) | df.head() df.head(3) |
tail(n) | 返回后 n 行。 n为可选参数,默认为5。 | s.tail() s.tail(3) | df.tail() df.tail(3) |
info() | 查看 DataFrame 的信息(如数据类型、非空值数、内存信息等)。 | s.info() | df.info() |
describe() | 查看数值型列的统计信息(如均值、标准差、最小值等)。 | s.describe() | df.describe() |
6. 数据处理
空值检测 – isna() / isnull() /notna() / notnull()
Pandas 中这些值会被识别为缺失值:numpy.nan、None、pandas.NA (Pandas 1.0+ 引入)、NaT (对于时间序列数据)(空字符串 ‘’ 默认不被视为缺失值)
import pandas as pd
import numpy as nps = pd.Series([1, 2, None, 4, 5])
df = pd.DataFrame({'A': [1, 2, np.nan, 4],'B': ['a', pd.NA, 'c', None],'C': [1.1, 2.2, 3.3, np.nan]
})
方法 | | |
---|---|---|
isna() / isnull() | 检查是否有缺失值,返回与原始对象形状相同的布尔对象。 True 表示对应位置是缺失值; False 表示对应位置不是缺失值。 | df.isna() s.isna() df.isnull() s.isnull() |
notna() / notnull() | 检查是否不是缺失值,返回与原始对象形状相同的布尔对象。 True 表示对应位置是缺失值; False 表示对应位置不是缺失值。 | df.notna()() s.notna()() df.notnull() s.notnull() |
删除数据 – dropna() /drop()/drop_duplicates()/pop()
- dropna()
dropna() 是 Pandas 中用于删除缺失值(NA/NaN值)的核心方法,它可以灵活地处理 DataFrame 或 Series 中的缺失数据。基本语法:
DataFrame.dropna(axis=0, how='any', thresh=None, subset=None, inplace=False)
参数 | |
---|---|
axis | 指定要删除的行还是列,默认为0表示删除行,1表示删除列。 |
how | 指定删除缺失值的条件,可选值为’any’和’all’。'any’表示只要存在缺失值就删除,'all’表示只有当所有值都是缺失值时才删除。 |
thresh | 指定一个阈值,表示要保留的行或列中至少有多少个非缺失值。 |
subset | 指定要考虑哪些列或行。 |
inplace | 是否在原地修改DataFrame,默认为False,表示不修改原DataFrame,而是返回一个新的DataFrame。 |
返回值 | 根据inplace值返回对应DataFrame。 |
使用示例:
import pandas as pd
s = pd.Series([1, 2, None, 4, 5])
print(s.dropna()) # 删除缺失值df = pd.DataFrame({'A': [1, 2, None, 4],'B': [None, 2, 3, 4],'C': [1, 2, 3, None]
})
df.dropna() # 删除含有任何缺失值的行
df.dropna(axis=1) # 删除含有缺失值的列
df.dropna(how='all') # 只删除全为缺失值的行
df.dropna(thresh=2) # 保留至少有2个非缺失值的行
df.dropna(subset=['col1', 'col2']) # 只在指定列检查缺失值
- drop()
pandas 的 drop() 方法用于删除指定的行或列,能够方便地从 DataFrame 或 Series 中删除不需要的部分。
基本语法:
DataFrame.drop(labels=None, axis=0, index=None, columns=None, level=None, inplace=False, errors='raise')
参数 | |
---|---|
labels | 要删除的行或列的标签。可以是单个标签或标签列表。 |
axis | 指定删除的轴。axis=0 表示删除行(默认),axis=1 表示删除列。 |
index | 指定要删除的行的索引。如果指定了 index,则忽略 labels 参数。 |
columns | 指定要删除的列的标签。如果指定了 columns,则忽略 labels 参数。 |
level | 如果 DataFrame 有多层索引(MultiIndex),则可以通过 level 指定要删除的层级。 |
inplace | 如果为 True,则直接在原 DataFrame 上进行修改,而不是返回一个新的 DataFrame。 |
errors | 控制当指定的标签不存在时的行为。errors=‘raise’ 表示抛出错误(默认),errors=‘ignore’ 表示忽略错误。 |
返回值 | 根据inplace值返回对应DataFrame。 |
使用示例:
import pandas as pd
s = pd.Series([10, 20, 30, 40], index=['a', 'b', 'c', 'd'])
# 删除单个标签
s.drop('a')
# 原地删除
s.drop(['a', 'c'], inplace=True)# 创建一个 DataFrame
df = pd.DataFrame({'A': [1, 2, 3, 4],'B': [5, 6, 7, 8],'C': [9, 10, 11, 12]
})
# 删除行,使用行标签 0 和 2
df.drop([0, 2], axis=0)
# 删除多个列
df.drop(columns=['B', 'C'])
# 删除满足条件的行
df.drop(df[df['A'] < 3].index) # 删除A列小于3的行
- drop_duplicates()
pandas 的 drop_duplicates() 方法用于删除 DataFrame 或 Series 中的重复值,并返回一个新的对象,或者在原地修改(如果指定了 inplace=True)。基本语法:
DataFrame.drop_duplicates(subset=None, keep='first', inplace=False, ignore_index=False)
参数 | |
---|---|
subset | 指定根据哪些列(或索引)来判断重复。如果为 None,则会基于所有列来判断重复。Series无此参数。 |
keep | 指定保留哪个重复值。 first(默认):保留第一次出现的重复项,删除后面的重复项。 last:保留最后一次出现的重复项,删除前面的重复项。 False:删除所有重复项。 |
inplace | 布尔值,默认为 False。如果设置为 True,则修改原始对象,不返回新的对象。 |
ignore_index | 布尔值,默认为 False。如果设置为 True,则重置索引,使返回的 DataFrame 或 Series 具有连续的整数索引。 |
返回值 | 根据inplace值返回对应DataFrame。 |
使用示例:
import pandas as pd# 创建一个 Series
s = pd.Series([1, 2, 2, 3, 4, 4, 5])
# 删除重复值
s.drop_duplicates()# 创建一个 DataFrame
df = pd.DataFrame({'A': [1, 2, 2, 3, 4, 4],'B': [10, 20, 20, 30, 40, 40]
})
# 删除重复的行
df.drop_duplicates()
# 仅根据列 'A' 删除重复值
df.drop_duplicates(subset='A')
# 在原地修改 DataFrame
df.drop_duplicates(inplace=True)
- pop()
填充缺失值 – fillna()
pandas 的 fillna() 方法用于填充 DataFrame 或 Series 中的缺失值(NaN)。通常使用不同的策略来填充缺失数据,如填充常数、前向填充、后向填充等。基本语法:
DataFrame.fillna(value=None, method=None, axis=None, inplace=False, limit=None, downcast=None)
参数 | |
---|---|
value | 用于填充缺失值的值或字典。可以是一个标量值、字典、Series 或 DataFrame。 |
method | 填充方法。 ● None:使用value参数指定的值填充(默认); ● ‘pad’/‘ffill’:向前填充(使用前一个有效值); ● ‘backfill’/‘bfill’:向后填充(使用后一个有效值)。 |
axis | 指定填充的方向,默认为 None,会对整个 DataFrame 填充。可以设置为 0(沿着行方向)或 1(沿着列方向)。Series无此参数。 |
inplace | 如果为 True,则在原 DataFrame 或 Series 上进行填充,否则返回新的对象。 |
limit | 最大填充次数,指定最多填充多少个缺失值。 |
downcast | 用于将数据类型转换为较小的类型。 ● ‘integer’:尝试将数值列向下转换为最小的整数类型。例如:从 float64 转为 int8/int16/int32 等; ● ‘signed’:尝试向下转换为有符号整数类型。类似于 ‘integer’ 但明确指定为有符号整数; ● ‘unsigned’:尝试向下转换为无符号整数类型。例如:从 float64 转为 uint8/uint16/uint32 等; ● ‘float’:尝试向下转换为更小的浮点类型。例如:从 float64 转为 float32; ● None (默认值):不执行任何向下转换; ● ‘infer’:尝试自动推断最合适的最小数据类型。Pandas 会根据数据自动选择最节省内存的类型。 |
返回值 | 根据inplace值返回对应DataFrame。 |
使用示例:
import pandas as pd# 创建一个包含 NaN 的 Series
s = pd.Series([1, 2, None, 4, None, 6])
# 使用常数填充 NaN 值
s.fillna(0)
# 字典为不同的 NaN 值填充不同的值(适用于 Series 的不同位置)
s.fillna({2: 99, 4: 88})
限制填充的次数
s_filled = s.fillna(0, limit=1)# 创建一个 DataFrame,其中包含 NaN 值
df = pd.DataFrame({'A': [1, 2, None, 4],'B': [None, 2, 3, 4]
})
# 使用常数填充缺失值
df.fillna(0)
# 使用字典为不同列填充不同的值
df.fillna({'A': 0, 'B': 99})
# 使用Series按索引对齐填充
fill_values = pd.Series([1, 2], index=['A', 'B'])
df.fillna(fill_values)
# 使用DataFrame按行列索引对齐填充
fill_df = pd.DataFrame({'A': [1, 1], 'B': [2, 2]}, index=df.index)
df.fillna(fill_df)
修改数据 – 直接赋值/replace()/apply()/applymap()/map()
在 Pandas 中,修改 Series 和 DataFrame 数据是非常常见的操作。以下是一些常见的修改数据的方式:
- 直接对索引和切片结果赋值
可以对 3. 索引和切片 中的索引和切片结果直接赋值以修改对应位置元素值。使用示例:
import pandas as pd
# 创建一个 Series
s = pd.Series([1, 2, 3, 4, 5])
# 修改索引为 2 的值
s[2] = 10
# 修改大于 3 的所有值为 100
s[s > 3] = 100
# 修改索引 0 和 3 的元素
s[[0, 3]] = [99, 88]# 创建一个 DataFrame
df = pd.DataFrame({'A': [1, 2, 3],'B': [4, 5, 6]
})
# 修改列 'A' 的所有值
df['A'] = [10, 20, 30]
# 修改列 'A' 中大于 15 的值
df.loc[df['A'] > 15, 'A'] = 100
# 修改列 'A' 中第一行、第二行数据
df.loc[0:1, 'A'] = 60
- replace 方法
replace() 是 Pandas 中用于替换数据的强大方法,可以对 Series 或 DataFrame 中的值进行灵活替换。基本语法:
DataFrame.replace(to_replace=None, value=None, inplace=False, limit=None, regex=False, method=None)
参数 | |
---|---|
to_replace | 指定需要替换的值,可以是一个标量、字典、列表、Series 或正则表达式。 ● 如果是标量,则会将该值替换为 value 中对应的值。 ● 如果是字典,搭配value参数值组成键值,可以定义多个值的替换规则。 ● 如果是列表,表示多个需要替换的值。 ● 如果是正则表达式,可以通过 regex 参数启用正则替换。 |
value | 指定替换的目标值,可以是标量、列表、字典、Series,与 to_replace 对应的值进行替换。 ● 如果 to_replace 为标量,value 应该是一个标量或者相同形状的 Series、list 或 numpy 数组。 ● 如果 to_replace 是字典,则搭配to_replace参数值组成键值,指定每个替换值。 |
inplace | 是否在原地替换。如果设置为 True,则会修改原始的 DataFrame 或 Series,否则会返回一个新的 DataFrame 或 Series,默认不修改原始数据。 |
limit | 限制替换的最大次数。 |
regex | 是否使用正则表达式进行替换,默认为 False。如果设置为 True,则 to_replace 和 value 可以是正则表达式模式。 ● True:to_replace 会被解释为正则表达式,可以进行模式匹配替换。 ● False:表示直接替换精确匹配的值。 |
method | 指定替换方法。如果传入 method,to_replace 和 value 必须是 NaN 或 None。method 主要用于填充缺失值。 ●’pad’ 或 ‘ffill’:使用前一个有效值进行填充。 ●’bfill’:使用后一个有效值进行填充。 |
使用示例:
import pandas as pd# Series示例
s = pd.Series([1, 2, 3, 4, 5])
s.replace(3, 30) # 将3替换为30
# Series字典替换
s.replace({1: 10, 2: 20}) # 特定值映射
# 替换字符串
s = pd.Series(['foo', 'fuz', 'bar'])
s.replace(r'^f.*', 'new', regex=True) # 以f开头的替换为new# DataFrame示例
df = pd.DataFrame({'A': [1,2,3], 'B': [4,5,6]})
df.replace(1, 100) # 将所有1替换为100
# DataFrame字典替换
df.replace({'A': {1: 100}, 'B': {4: 400}}) # A列1→100, B列4→400
# 整个DataFrame统一替换
df.replace({1: 100, 4: 400}) # 所有列中的1→100, 4→400
# DataFrame正则替换
df = pd.DataFrame({'A': ['foo', 'bar'], 'B': ['fuz', 'baz']})
df.replace(r'^ba.$', 'new', regex=True) # 替换所有匹配正则的值
- apply 方法
pandas 中的 apply 函数用于沿 Series 或 DataFrame 的指定轴(行或列)应用一个自定义的函数。它是非常灵活且强大的工具,可以帮助我们对数据进行复杂的操作和变换。基本语法:
Series.apply(func, convert_dtype=True, args=(), **kwds)
DataFrame.apply(func, axis=0, raw=False, result_type=None, args=(), **kwds)
参数 | |
---|---|
func | 要应用的函数。这个函数可以是自定义函数,也可以是内置函数。 对于 Series,func 会应用到每个元素。 对于 DataFrame,func 会应用到每个列或每个行(取决于 axis 参数)。 |
axis | 仅适用于 DataFrame。指定操作的轴,决定了函数是作用于行还是列。 0(默认值):表示沿列(即逐列应用函数)。 1 :表示沿行(即逐行应用函数)。 |
raw | 仅适用于 DataFrame。布尔值,将数据传递给函数时是否以原始数组(numpy 数组)的形式传递。 False(默认):将每行/列作为 Series 传递给函数。 True:将作为 ndarray 对象传递,性能更好。 |
result_type | 适用于 DataFrame。控制返回结果的类型。 ● None(默认):返回 Series 或 DataFrame。 ● expand:如果 func 返回多个值,将它们展开成新的列(适用于 DataFrame 中的列)。 ● reduce:返回聚合的结果。 ● broadcast:返回与原 DataFrame 相同的形状。 ● args:传递给 func 的位置参数元组。 ● **kwargs:传递给 func 的关键字参数。 |
convert_dtype | 仅适用于 Series。是否自动转换数据类型。默认为 True,即会尝试自动推断返回数据的类型并转换;如果设置为 False,则不进行类型转换。 |
args | 传递给 func 的位置参数元组。 |
**kwargs | 传递给 func 的关键字参数。 |
返回值 | 一个新的 Series 或 DataFrame。 |
使用示例:
import pandas as pd# 创建一个 Series
s = pd.Series([1, 2, 3, 4, 5])
# 定义一个简单的函数,计算每个元素的平方
def square(x):return x ** 2
# 使用 apply 函数将 square 应用于每个元素
s= s.apply(square) # 等价形式:s.apply(lambda x: x ** 2)# 创建一个 DataFrame
df = pd.DataFrame({'A': [1, 2, 3],'B': [4, 5, 6]
})
# 对每一列应用一个函数,计算每列的和
df = df.apply(sum)
# 对每一列的各元素加1
df.apply(lambda x: x + 1)
- applymap 方法
applymap() 是 pandas DataFrame 的一个方法,用于对 DataFrame 中的每个元素应用一个函数。基本语法:
DataFrame.applymap(func, na_action=None, **kwargs)
参数 | |
---|---|
func | 要应用于每个元素的函数。可以是一个 Python 函数、lambda 函数或其他可调用对象,函数应该接受一个标量值并返回一个标量值。 |
na_action | 如何处理 NA 值,默认None。如果设为 ‘ignore’,则 NA 值将保持不变。 |
**kwargs | 传递给 func 的额外关键字参数。 |
返回值 | 返回一个新的 DataFrame。 |
使用示例:
import pandas as pd# 示例一:对字符串进行大写处理
# 创建一个 DataFrame,包含字符串
df = pd.DataFrame({'A': ['apple', 'banana', 'cherry'],'B': ['dog', 'elephant', 'fox']
})
# 定义一个函数,将字符串转换为大写
def to_upper(x):return x.upper()
# 使用 applymap 对每个元素应用 to_upper 函数
df_upper = df.applymap(to_upper)
print(df_upper)# 示例二:自定义函数自带参数,对数值进行平方操作
def power(x, exponent=2):return x ** exponent
df = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6]})
# 使用额外的关键字参数
result = df.applymap(power, exponent=3)
print(result)
- map 方法
map() 是 pandas Series 的一个方法,用于对 Series 中的每个元素应用一个函数或根据映射关系进行转换。基本语法:
参数 | |
---|---|
arg | 可以是以下类型之一: ● 字典:用于映射替换值的字典,键为原始值,值为替换后的值。 ● 函数:应用到每个元素的函数。 ● Series:映射原始 Series 与目标 Series 中的对应关系,使用 Series 中的值来替换原 Series 中的值。 ● None:当没有提供 arg 时,返回 Series 自身(默认)。 |
na_action | 如何处理 NA 值,默认None。如果设为 ‘ignore’,则 NA 值将保持不变。 |
返回值 | 返回一个新的 Series。 |
import pandas as pd# 使用函数计算字符串长度
s = pd.Series(['cat', 'dog', 'bird', 'cat'])
result = s.map(len)
print(result)# 使用字典进行映射
s = pd.Series(['apple', 'banana', 'orange', 'apple'])
fruit_colors = {'apple': 'red', 'banana': 'yellow', 'orange': 'orange'}
result = s.map(fruit_colors)
print(result)# 使用 Series 进行映射
s1 = pd.Series(['a', 'b', 'c'], index=[1, 2, 3])
s2 = pd.Series([10, 20, 30], index=['a', 'b', 'c'])
result = s1.map(s2)
print(result)
增加数据 – 赋值新索引/insert()
在 pandas 中,可以通过多种方法向 DataFrame 或 Series 中增加数据。以下是几种常见的方法:
- 赋值新索引
可以直接通过新索引赋值添加数据到 Series ;给新行列赋值添加数据到 DataFrame ,新行的值可以是标量、列表、Series 或 NumPy 数组。
使用示例:
import pandas as pds = pd.Series([1, 2, 3])
# 直接通过新索引添加
s[3] = 4 # 等价 s.loc[3] = 4# 创建一个简单的 DataFrame
df = pd.DataFrame({'A': [1, 2, 3],'B': [4, 5, 6]
})
# 添加新列 'C'
df['C'] = [7, 8, 9]
# 使用 loc 添加新行
df.loc[3] = [10, 11, 12]]
- insert()
pandas 的 insert() 方法用于将新列插入到现有的 DataFrame 中。它可以指定插入列的位置,从而控制列的顺序。
参数 | |
---|---|
loc | 表示新列的插入位置。loc 是一个整数值,表示要插入列的位置索引(基于 0 的索引)。 |
column | 表示要插入的列的名称,将作为 DataFrame 中的新列标题。 |
value | 表示要插入的新列的值。可以是一个标量值(所有行使用相同的值)、一个列表、一个 Series(列表或 Series长度必须与 DataFrame 中的行数一致)或一个 DataFrame。 |
allow_duplicates | 是否允许列名重复, 默认值 False。如果设置为 True,则允许在 DataFrame 中存在重复的列名。如果设置为 False,则如果新列的列名已经存在,将引发 ValueError 异常。 |
返回值 | 返回修改后的 DataFrame,原 DataFrame 将被直接修改。 |
使用示例:
import pandas as pd
# 在第1列位置插入新列
df = pd.DataFrame({'A': [1, 2], 'B': [3, 4]})
df.insert(1, 'C', [5, 6])
# 插入标量值(自动广播)
df.insert(0, 'Flag', True) # 所有行插入相同值# 插入Series
s = pd.Series([7, 8], name='D')
df.insert(2, s.name, s) # 插入Series并自动使用其名称
更改数据类型 – astype()
在 pandas 中,您可以使用 astype() 方法来更改 DataFrame 或 Series 中的数据类型。astype() 允许您将数据从一种类型转换为另一种类型,支持常见的数据类型转换,如整数、浮点数、字符串、日期等。基本语法:
DataFrame.astype(dtype, copy=True, errors='raise')
参数 | |
---|---|
dtype | 表示目标数据类型。可以是一个单独的数据类型(如 int, float, str 等),也可以是字典,指定每列的目标数据类型。 |
copy | 是否返回一个新的对象,默认为 True,表示复制数据。如果为 False,则会就地修改原始对象。 |
errors | 控制转换错误行为。 ‘raise’:如果出现转换错误,抛出异常。 ‘ignore’:如果发生错误,保持原来的数据类型。 |
返回值 | 根据copy值返回对应DataFrame。 |
使用示例:
import pandas as pd# 创建 Series
s = pd.Series(['1', '2', '3'])
# 将Series转换为float类型
s = s.astype('float64')
# 转换为字符串类型
s = s.astype('str')# 创建 DataFrame
df = pd.DataFrame({'A': ['1', '2', '3'],'B': ['4', '5', '6']
})
# 将列 'A' 从字符串转换为整数
df['A'] = df['A'].astype(int)
# 将列 'A' 转换为整数类型,列 'B' 转换为浮动类型
df = df.astype({'A': 'int64', 'B': 'float64'})
7. 数据运算
Pandas 提供了丰富的数据运算功能,可以高效地对 Series 和 DataFrame 进行各种数学和逻辑运算。值得一提的是,任何与 NaN 进行运算的结果都会是 NaN,可以事先处理缺失值。
算术运算 (+, -, *, /, //, %, **)
Pandas 支持直接使用 +, -, *, /, //, %, ** 等运算符进行逐元素运算。
import pandas as pd
import numpy as np# 创建示例数据
s1 = pd.Series([1, 2, 3, 4])
s2 = pd.Series([10, 20, 30, 40])
df1 = pd.DataFrame({'A': [1, 2], 'B': [3, 4]})
df2 = pd.DataFrame({'A': [10, 20], 'B': [30, 40]})
运算类型 | 方法 | 运算符 | Series示例 | DataFrame示例 | ||
---|---|---|---|---|---|---|
加法运算 | add() | + |
|
| ||
减法运算 | sub() | - |
|
| ||
乘法运算 | mul() | * |
|
| ||
除法运算 | div() | / |
|
| ||
整数除法 | floordiv() | // |
|
| ||
取模运算 | mod() | % |
|
| ||
幂运算 | pow() | % |
|
|
广播运算
当对 DataFrame 和 Series 进行运算时,pandas 会进行广播(即将 Series 的数据广播到 DataFrame 上),如果 Series 的索引与 DataFrame 的列索引对齐,则按列对齐进行运算。
import pandas as pd
import numpy as np# 创建示例数据
s1 = pd.Series([1, 2, 3, 4])
df1 = pd.DataFrame({'A': [1, 2], 'B': [3, 4]})# 与标量运算
print(s1 * 5) # Series 每个元素乘以5
print(df1 * 2) # DataFrame 每个元素乘以2# Series 与 DataFrame 运算
row = pd.Series([10, 20], index=['A', 'B'])
print(df1 + row) # 每行加上row
col = pd.Series([100, 200], index=[0, 1])
print(df1.add(col, axis=0)) # 每列加上col
比较运算 (==, !=, >, <, >=, <=)
Pandas 提供了丰富的比较运算功能,可以对 Series 和 DataFrame 进行元素级别的比较操作。比较运算会根据行列的标签对齐数据,比较运算返回的是布尔值(True/False)的 Series 或 DataFrame。
import pandas as pd
import numpy as np# 创建示例数据
s1 = pd.Series([1, 2, 3, 4])
s2 = pd.Series([10, 20, 30, 40])
df1 = pd.DataFrame({'A': [1, 2], 'B': [3, 4]})
df2 = pd.DataFrame({'A': [10, 20], 'B': [30, 40]})
运算类型 | 方法 | 运算符 | Series示例 | DataFrame示例 | ||
---|---|---|---|---|---|---|
等于 | eq() | == |
|
| ||
不等于 | ne() | != |
|
| ||
大于 | gt() | > |
|
| ||
小于 | lt() | < |
|
| ||
大于或等于 | ge() | >= |
|
| ||
小于或等于 | le() | <= |
|
|
逻辑运算 (&、|、~、^)/all() /any()
&(按位与)、|(按位或)、 ~(按位非)和 ^(按位异或)运算符可以用来组合多个条件。以Series为例,DataFrame同理,示例如下:
import pandas as pd# 创建两个 Series
s1 = pd.Series([1, 2, 3], index=['A', 'B', 'C'])
s2 = pd.Series([1, 3, 3], index=['A', 'B', 'C'])# 逻辑与 (&)
result = (s1 > 1) & (s2 < 3)# 逻辑或 (|)
result = (s1 > 1) | (s2 < 3)# 逻辑非 (~)
result = ~(s1 == s2)# 逻辑异或 (^)
result = s1 ^ s2 # 等价于 s1.xor(s2)
- all()
all() 方法用于检查 Series 或 DataFrame 中所有元素是否为 True。如果所有元素都为 True,则返回 True,否则返回 False。基本语法:
DataFrame.all(axis=0, bool_only=None, skipna=True, **kwargs)
参数 | |
---|---|
axis | 指定计算方向。 0 或 ‘index’: 按列计算(对每列的所有行进行计算)。 1 或 ‘columns’: 按行计算(对每行的所有列进行计算) Series不包含此参数。 |
bool_only | 用于是否只利用序列中的Boolean值进行判断,默认为 None。 如果为 True,则只考虑布尔类型的。 如果为 False,则所有行或列都会被考虑,包括非布尔类型。 |
skipna | 是否跳过NA/NaN值。 True: 忽略NA/NaN(默认)。 False: 将NA/NaN视为False。 |
**kwargs | 其他关键字参数,目前没有使用。 |
返回值 | 一个series或标量。 |
使用示例:
import pandas as pd# Series示例
s = pd.Series([True, True, np.nan])
print(s.all()) # 输出: True (skipna=True 时忽略 NA)
print(s.all(skipna=False)) # 输出: False# DataFrame示例
df = pd.DataFrame({'A': [1, 2, 3],'B': [0, 1, 1]
})
print(df.all())
print(df.all(axis=1))
- any()
any() 方法用于检查 Series 或 DataFrame 中是否至少有一个元素为 True。如果有任何一个元素为 True,则返回 True,否则返回 False。
基本语法:
DataFrame.any(axis=0, bool_only=None, skipna=True, **kwargs)
参数 | |
---|---|
axis | 指定计算方向。 0 或 ‘index’: 按列计算(对每列的所有行进行计算)。 1 或 ‘columns’: 按行计算(对每行的所有列进行计算) Series不包含此参数。 |
bool_only | 用于是否只利用序列中的Boolean值进行判断,默认为 None。 如果为 True,则只考虑布尔类型的。 如果为 False,则所有行或列都会被考虑,包括非布尔类型。 |
skipna | 是否跳过NA/NaN值。 True: 忽略NA/NaN(默认)。 False: 将NA/NaN视为False。 |
**kwargs | 其他关键字参数,目前没有使用。 |
返回值 | 一个series或标量。 |
使用示例:
import pandas as pd# 创建一个 Series
s = pd.Series([False, False, True])
# 检查是否至少有一个元素为 True
result = s.any()# 创建一个 DataFrame
df = pd.DataFrame({'A': [False, False, False],'B': [False, True, False]
})
# 检查每一列是否至少有一个元素为 True
result = df.any()
描述性统计 sum()/mean()/median()/mode()/std()/var()/min()/max()
Pandas 提供了丰富的统计运算功能,可以方便地对数据进行描述性统计分析。
- sum() – 求和
DataFrame.sum(axis=None, skipna=True, level=None, numeric_only=None, min_count=0, **kwargs)
参数 | |
---|---|
axis | 指定沿哪个轴进行求和。 ● axis=0(默认):对每一列进行求和。 ● axis=1:对每一行进行求和。 Series不含此参数。 |
skipna | 是否忽略缺失值 (NaN),默认为 True。 ● True: 自动跳过NaN值(默认) ● False: 包含NaN值,如果存在NaN则结果为NaN |
level | 如果 DataFrame 有 MultiIndex,按指定级别进行求和。 Series不含此参数。 |
numeric_only | 是否仅对数值类型进行求和。 ● False: 尝试对所有列进行计算 ● True: 只计算数值列 |
min_count | 执行操作所需的最小非NA值数,如果非NA值少于min_count,结果为NaN |
**kwargs | 其他关键字参数,目前没有使用。 |
返回值 | 返回一个Series 或 标量。 |
import pandas as pd
import numpy as np# DataFrame示例
df = pd.DataFrame({'A': [1, 2, 3, np.nan],'B': [4, 5, np.nan, 7],'C': ['x', 'y', 'z', 'w'] # 非数值列
})# Series示例
s = pd.Series([1, 2, np.nan, 4])print("DataFrame 列求和:")
print(df.sum()) # 默认axis=0,列求和print("\nDataFrame 行求和:")
print(df.sum(axis=1)) # 行求和print("\nSeries 求和:")
print(s.sum()) # 输出7.0 (自动跳过NaN)
- mean() – 平均值
DataFrame.mean(axis=None, skipna=True, level=None, numeric_only=None, **kwargs)
参数 | |
---|---|
axis | 指定沿哪个轴计算均值。 ● axis=0(默认):对每一列计算均值。 ● axis=1:对每一行进行计算均值。 Series不含此参数。 |
skipna | 是否忽略缺失值 (NaN),默认为 True。 ● True: 自动跳过NaN值(默认) ● False: 包含NaN值,如果存在NaN则结果为NaN |
level | 如果 DataFrame 有 MultiIndex,按指定级别计算均值。 Series不含此参数。 |
numeric_only | 是否仅对数值类型计算均值。 ● False: 尝试对所有列进行计算 ● True: 只计算数值列 |
**kwargs | 其他关键字参数,目前没有使用。 |
返回值 | 返回一个Series 或 标量。 |
import pandas as pd
import numpy as np# DataFrame示例
df = pd.DataFrame({'A': [1, 2, 3, np.nan],'B': [4, 5, np.nan, 7],'C': ['x', 'y', 'z', 'w'] # 非数值列
})# Series示例
s = pd.Series([1, 2, np.nan, 4])print("\nDataFrame 列平均值:")
print(df.mean()) # 计算数值列的平均值print("\nDataFrame 行平均值:")
print(df.mean(axis=1))print("\nSeries 平均值:")
print(s.mean()) # 输出2.333... (7/3)
- median() – 中位数
DataFrame.median(axis=None, skipna=True, level=None, numeric_only=None, **kwargs)
参数 | |
---|---|
axis | 指定沿哪个轴计算中位数。 ● axis=0(默认):对每一列计算中位数。 ● axis=1:对每一行进行计算中位数。 Series不含此参数。 |
skipna | 是否忽略缺失值 (NaN),默认为 True。 ● True: 自动跳过NaN值(默认) ● False: 包含NaN值,如果存在NaN则结果为NaN |
level | 如果 DataFrame 有 MultiIndex,按指定级别计算中位数。 Series不含此参数。 |
numeric_only | 是否仅对数值类型计算中位数。 ● False: 尝试对所有列进行计算 ● True: 只计算数值列 |
**kwargs | 其他关键字参数,目前没有使用。 |
返回值 | 返回一个Series 或 标量。 |
import pandas as pd
import numpy as np# DataFrame示例
df = pd.DataFrame({'A': [1, 2, 3, np.nan],'B': [4, 5, np.nan, 7],'C': ['x', 'y', 'z', 'w'] # 非数值列
})print("\n列中位数:")
print(df.median())print("\nSeries中位数:")
print(pd.Series([1, 2, 3, 4, 100]).median()) # 输出3
- mode() – 众数
DataFrame.mode(axis=0, numeric_only=None, dropna=True, **kwargs)
参数 | |
---|---|
axis | 指定沿哪个轴计算众数。 ● axis=0(默认):对每一列计算众数。 ● axis=1:对每一行进行计算众数。 Series不含此参数。 |
numeric_only | 是否仅对数值类型计算众数。 ● False: 尝试对所有列进行计算 ● True: 只计算数值列 |
dropna | 是否忽略缺失值 (NaN),默认为 True。 ● True: 自动跳过NaN值(默认) ● False: 包含NaN值,如果存在NaN则结果为NaN |
**kwargs | 其他关键字参数,目前没有使用。 |
返回值 | 返回一个Series 或 标量。 |
import pandas as pd
import numpy as npdf_mode = pd.DataFrame({'A': [1, 2, 2, 3],'B': ['x', 'x', 'y', 'y']
})print("\n列众数:")
print(df_mode.mode())print("\nSeries众数:")
print(pd.Series([1, 2, 2, 3, 3]).mode()) # 返回2和3
- std() – 标准差
DataFrame.std(axis=None, skipna=True, ddof=1, numeric_only=None, **kwargs)
参数 | |
---|---|
axis | 指定沿哪个轴计算标准差。 ● axis=0(默认):对每一列计算标准差。。 ● axis=1:对每一行进行计算标准差。 Series不含此参数。 |
skipna | 是否忽略缺失值 (NaN),默认为 True。 ● True: 自动跳过NaN值(默认) ● False: 包含NaN值,如果存在NaN则结果为NaN |
ddof | 自由度差值,用于计算无偏估计,默认为 1。 ● ddof=0:总体标准差。 ● ddof=1:样本标准差。 |
numeric_only | 是否仅对数值类型计算标准差。 ● False: 尝试对所有列进行计算 ● True: 只计算数值列 |
**kwargs | 其他关键字参数,目前没有使用。 |
返回值 | 返回一个Series 或 标量。 |
import pandas as pd
import numpy as np# DataFrame示例
df = pd.DataFrame({'A': [1, 2, 3, np.nan],'B': [4, 5, np.nan, 7],'C': ['x', 'y', 'z', 'w'] # 非数值列
})print("\n列标准差:")
print(df.std())print("\nSeries标准差:")
print(pd.Series([1, 2, 3, 4]).std()) # 样本标准差≈1.29
- std() – 方差
DataFrame.var(axis=None, skipna=True, ddof=1, numeric_only=None, **kwargs)
参数 | |
---|---|
axis | 指定沿哪个轴计算方差。 ● axis=0(默认):对每一列计算方差。 ● axis=1:对每一行进行计算方差。 Series不含此参数。 |
skipna | 是否忽略缺失值 (NaN),默认为 True。 ● True: 自动跳过NaN值(默认) ● False: 包含NaN值,如果存在NaN则结果为NaN |
ddof | 自由度差值,用于计算无偏估计,默认为 1。 ● ddof=0:总体方差 ● ddof=1:样本方差 |
numeric_only | 是否仅对数值类型计算方差。 ● False: 尝试对所有列进行计算 ● True: 只计算数值列 |
**kwargs | 其他关键字参数,目前没有使用。 |
返回值 | 返回一个Series 或 标量。 |
import pandas as pd
import numpy as np# DataFrame示例
df = pd.DataFrame({'A': [1, 2, 3, np.nan],'B': [4, 5, np.nan, 7],'C': ['x', 'y', 'z', 'w'] # 非数值列
})print("\n列方差:")
print(df.var())print("\nSeries方差:")
print(pd.Series([1, 2, 3, 4]).var()) # ≈1.67
- min() – 最小值
DataFrame.min(axis=None, skipna=True, level=None, numeric_only=None, **kwargs)
参数 | |
---|---|
axis | 指定沿哪个轴计算最小值。 ● axis=0(默认):对每一列计算最小值。 ● axis=1:对每一行计算最小值。 Series不含此参数。 |
skipna | 是否忽略缺失值 (NaN),默认为 True。 ● True: 自动跳过NaN值(默认) ● False: 包含NaN值,如果存在NaN则结果为NaN |
level | 如果 DataFrame 有 MultiIndex,按指定级别计算最小值。 Series不含此参数。 |
numeric_only | 是否仅对数值类型计算最小值。 ● False: 尝试对所有列进行计算 ● True: 只计算数值列 |
min_count | 执行操作所需的最小非NA值数,如果非NA值少于min_count,结果为NaN |
**kwargs | 其他关键字参数,目前没有使用。 |
返回值 | 返回一个Series 或 标量。 |
import pandas as pd
import numpy as np# DataFrame示例
df = pd.DataFrame({'A': [1, 2, 3, np.nan],'B': [4, 5, np.nan, 7],'C': ['x', 'y', 'z', 'w'] # 非数值列
})print("\n列最小值:")
print(df.min())print("\nSeries最小值:")
print(pd.Series([5, 2, 8, 1]).min()) # 输出1
- max() – 最大值
DataFrame.max(axis=None, skipna=True, level=None, numeric_only=None, **kwargs)
参数 | |
---|---|
axis | 指定沿哪个轴计算最大值。 ● axis=0(默认):对每一列计算最大值。 ● axis=1:对每一行计算最大值。 Series不含此参数。 |
skipna | 是否忽略缺失值 (NaN),默认为 True。 ● True: 自动跳过NaN值(默认) ● False: 包含NaN值,如果存在NaN则结果为NaN |
level | 如果 DataFrame 有 MultiIndex,按指定级别计算最大值。 Series不含此参数。 |
numeric_only | 是否仅对数值类型计算最大值。 ● False: 尝试对所有列进行计算 ● True: 只计算数值列 |
min_count | 执行操作所需的最小非NA值数,如果非NA值少于min_count,结果为NaN |
**kwargs | 其他关键字参数,目前没有使用。 |
返回值 | 返回一个Series 或 标量。 |
import pandas as pd
import numpy as np# DataFrame示例
df = pd.DataFrame({'A': [1, 2, 3, np.nan],'B': [4, 5, np.nan, 7],'C': ['x', 'y', 'z', 'w'] # 非数值列
})print("\n列最大值:")
print(df.max())print("\nSeries最大值:")
print(pd.Series([5, 2, 8, 1]).max()) # 输出8
分组统计 groupby()
分组统计是Pandas中非常重要的功能,它允许我们对数据集进行分组并对各组应用统计函数。
- groupby() 方法
分组统计主要通过 groupby() 方法实现,基本语法:
DataFrame.groupby(by, axis=0, level=None, as_index=True, sort=True, group_keys=True, squeeze=False, observed=False, dropna=True)
参数 | |
---|---|
by | 用于分组的列或列名列表、数组、字典或 Series。它决定了如何将数据分组。常见的方式是使用列名进行分组。 |
axis | 用于指定分组的轴,默认值 0。axis=0 代表按行分组;axis=1 代表按列分组。 |
level | 当数据是多层索引(MultiIndex)时,指定分组的层级。 |
as_index | 是否将分组列作为结果DataFrame的索引,默认True。如果为 True,则用分组的列作为结果的索引;如果为 False,则不将分组列作为结果的索引。 |
sort | 是否对分组键排序,默认True。如果为 True,则按分组的列对数据进行排序;如果为 False,则不进行排序。 |
group_keys | 是否在结果中保留分组的键值(键值即分组列的值),默认值 True。如果为 True,则保留分组键;如果为 False,则去除分组键。 |
squeeze | 减少返回类型的维度,默认值 False。如果为 True,则在可能的情况下将返回结果压缩成更小的数据结构(如 Series)。 |
observed | 在进行分组时,是否只使用数据中出现的分类(当分组变量是 Categorical 类型时),默认值 False。 |
dropna | 是否排除分组键中的NA值,默认True。 |
返回值 | 返回的是一个GroupBy对象。这个对象提供了多种方法来对分组后的数据进行操作,比如计算、聚合等。 |
使用示例:
import pandas as pddf = pd.DataFrame({'A': ['foo', 'bar', 'foo', 'bar', 'foo', 'bar', 'foo', 'foo'],'B': ['one', 'one', 'two', 'three', 'two', 'two', 'one', 'three'],'C': [1, 2, 3, 4, 5, 6, 7, 8],'D': [10, 20, 30, 40, 50, 60, 70, 80]
})# 按A列分组
grouped = df.groupby('A')
print(list(grouped))
# 按多列分组
grouped_multi = df.groupby(['A', 'B'])
print(list(grouped_multi))
groupby的过程就是将原有的DataFrame按照groupby的字段(这里是company),划分为若干个分组DataFrame,被分为多少个组就有多少个分组DataFrame。
- 分组后的操作:聚合(Aggregation)
分组后的常见操作包括对每个组进行聚合统计,如求和、均值、最大值、最小值等。
聚合操作:
sum():对每组数据求和。
mean():计算每组的均值。
count():统计每组数据的非空元素数量。
min():计算每组的最小值。
max():计算每组的最大值。
std():计算每组的标准差。
var():计算每组的方差。
使用示例:
import pandas as pddf = pd.DataFrame({'A': ['foo', 'bar', 'foo', 'bar', 'foo', 'bar', 'foo', 'foo'],'B': ['one', 'one', 'two', 'three', 'two', 'two', 'one', 'three'],'C': [1, 2, 3, 4, 5, 6, 7, 8],'D': [10, 20, 30, 40, 50, 60, 70, 80]
})# 计算每组的平均值
print(df.groupby('A').mean())# 对特定列进行聚合
print(df.groupby('A')['C'].sum())# 多列聚合
print(df.groupby('A')[['C', 'D']].mean())
- 自定义聚合函数:agg() 方法
除常见操作外,agg() 方法允许我们对每个组应用多个聚合函数,甚至是自定义的函数。基本语法:
DataFrame.groupby(...).agg(func=None, axis=0, *args, **kwargs)
参数 | |
---|---|
func | 聚合函数,可以是字符串、函数、列表或字典。 |
axis | 用于指定分组的轴,默认值 0。axis=0 代表按行分组;axis=1 代表按列分组。 |
返回值 | 返回一个Series 或 DataFrame。 |
使用示例:
import pandas as pddf = pd.DataFrame({'A': ['foo', 'bar', 'foo', 'bar', 'foo', 'bar', 'foo', 'foo'],'B': ['one', 'one', 'two', 'three', 'two', 'two', 'one', 'three'],'C': [1, 2, 3, 4, 5, 6, 7, 8],'D': [10, 20, 30, 40, 50, 60, 70, 80]
})# 使用多个聚合函数
print(df.groupby('A')['C'].agg(['mean', 'sum', 'std']))# 对多列应用不同聚合函数
print(df.groupby('A').agg({'C': 'sum','D': ['mean', 'std']
}))# 自定义聚合函数
def range_func(x):return x.max() - x.min()
print(df.groupby('A').agg({'C': range_func,'D': ['mean', range_func]
}))
- 分组后组内转换:transform()方法
有时候需要在分组后对每组数据进行转换,比如标准化、规范化或者填充缺失值。transform() 方法可以用来对每组数据进行转换,它返回一个和原始数据形状相同的结果。
使用示例:
import pandas as pddf = pd.DataFrame({'A': ['foo', 'bar', 'foo', 'bar', 'foo', 'bar', 'foo', 'foo'],'B': ['one', 'one', 'two', 'three', 'two', 'two', 'one', 'three'],'C': [1, 2, 3, 4, 5, 6, 7, 8],'D': [10, 20, 30, 40, 50, 60, 70, 80]
})# 计算每组相对于组均值的标准化值
df.groupby('A')['C'].transform(lambda x: (x - x.mean()) / x.std())
- 分组自定义函数:apply() 方法
apply() 方法允许我们对每个组应用一个自定义函数。apply() 可以用来执行复杂的操作,并且返回一个不同形状的结果。
使用示例:
import pandas as pd
import numpy as np# 示例一
df = pd.DataFrame({'A': ['foo', 'bar', 'foo', 'bar', 'foo', 'bar', 'foo', 'foo'],'B': ['one', 'one', 'two', 'three', 'two', 'two', 'one', 'three'],'C': [1, 2, 3, 4, 5, 6, 7, 8],'D': [10, 20, 30, 40, 50, 60, 70, 80]
})
# 对每组应用自定义函数
def custom_func(group):return pd.Series({'C_sum': group['C'].sum(),'D_mean': group['D'].mean()})
print(df.groupby('A').apply(custom_func))# 示例二
company=["A","B","C"]
data=pd.DataFrame({"company":[company[x] for x in np.random.randint(0,len(company),10)],"salary":np.random.randint(5,50,10),"age":np.random.randint(15,50,10)}
)def get_oldest_staff(x):# 输入的数据按照age字段进行排序df = x.sort_values(by = 'age',ascending=True)# 返回最后一条数据return df.iloc[-1,:]oldest_staff = data.groupby('company',as_index=False).apply(get_oldest_staff)
print(oldest_staff)
8. 拼接合并
Pandas提供了多种数据拼接和合并的方法,主要包括concat()、merge()和join()。
concat() – 简单堆叠/拼接
concat() 用于沿着某一轴拼接多个 DataFrame 或 Series。它可以纵向(按行)或横向(按列)合并多个对象。基本语法:
pandas.concat(objs, axis=0, join='outer', ignore_index=False, keys=None, levels=None, names=None, verify_integrity=False, sort=False, copy=True)
参数 | |
---|---|
objs | 要连接的Series或DataFrame对象的序列(列表或字典) |
axis | 连接轴方向。 ● 0或’index’:垂直堆叠(默认)。 ● 1或’columns’:水平拼接。 |
join | 连接方式。 ● ‘outer’:外连接,保留所有数据(默认) ● ‘inner’:内连接,只保留共有列/索引 |
ignore_index | 是否重置索引,默认为 False。 ● False:保留原索引(默认) ● True:忽略原索引,生成新索引(0,1,2…) |
keys | 用于生成层次化索引的键。它会把拼接的对象分层。例如:keys=[‘x’, ‘y’, ‘z’] |
levels | 用于设置层次化索引的级别。 |
names | 为多层索引的级别命名 |
verify_integrity | 检查是否有重复的索引。 ●False:不检查(默认) ●True:检查,有重复则报错 |
sort | 排序合并后的列名。 ●False:不排序(默认) ●True:排序 |
copy | 是否复制数据。 ●True:复制(默认) ●False:不复制(可能修改原数据) |
返回值 | 根据copy值返回对应DataFrame。 |
使用示例:
import pandas as pd
s1 = pd.Series([1, 2, 3], name='A')
s2 = pd.Series([4, 5, 6], name='B')
# 垂直堆叠两个Series
result = pd.concat([s1, s2])
# 水平拼接变成一个DataFrame
result = pd.concat([s1, s2], axis=1)df1 = pd.DataFrame({'A': ['A0', 'A1'], 'B': ['B0', 'B1']})
df2 = pd.DataFrame({'A': ['A2', 'A3'], 'B': ['B2', 'B3']})
# 垂直堆叠
result = pd.concat([df1, df2])
# 水平拼接
result = pd.concat([df1, df2], axis=1)
# 添加keys创建多层索引
result = pd.concat([df1, df2], keys=['df1', 'df2'])
merge() – 基于键值合并
merge()用于基于一个或多个键将两个DataFrame合并,类似SQL的JOIN操作。基本语法:
pandas.merge(left, right, how='inner', on=None, left_on=None, right_on=None, left_index=False, right_index=False, sort=True, suffixes=('_x', '_y'), copy=True, indicator=False, validate=None)
参数 | |
---|---|
left | 左侧DataFrame |
right | 右侧DataFrame |
how | 合并方式。 ●’inner’: 内连接,只保留匹配行(默认) ●’outer’: 外连接,保留所有行 ●’left’: 左连接,保留左表所有行 ●’right’: 右连接,保留右表所有行 ●’cross’: 笛卡尔积 ●on: 用于连接的列名(必须在两个DataFrame中都存在) |
left_on | 左表用于连接的列名 |
right_on | 右表用于连接的列名 |
left_index | 是否使用左表的索引作为连接键。 ●False:不使用(默认) ●True:使用 |
right_index | 是否使用右表的索引作为连接键。 ●False:不使用(默认) ●True:使用 |
sort | 是否对合并的结果进行排序。 ●False:不排序(默认) ●True:排序 |
suffixes | 如果两个 DataFrame 中有相同的列名,通过这个参数来避免列名冲突。默认是 (‘_x’, ‘_y’)。 |
copy | 是否复制数据。 ●True:复制(默认) ●False:不复制 |
indicator | 是否添加合并来源标记列。 ●False:不添加(默认) ●True或字符串:添加列,显示每行来源(‘left_only’, ‘right_only’, ‘both’) |
validate | 验证合并类型。 ●None:不验证(默认) ●"one_to_one"或"1:1" ●"one_to_many"或"1:m" ●"many_to_one"或"m:1" ●"many_to_many"或"m:m" |
返回值 | 根据copy值返回对应DataFrame。 |
使用示例:
import pandas as pd
left = pd.DataFrame({'key': ['K0', 'K1', 'K2'], 'A': ['A0', 'A1', 'A2']})
right = pd.DataFrame({'key': ['K0', 'K1', 'K3'], 'B': ['B0', 'B1', 'B3']})
# 内连接
result = pd.merge(left, right, on='key')
# 左连接
result = pd.merge(left, right, on='key', how='left')
# 使用不同列名合并
result = pd.merge(left, right, left_on='key', right_on='key', how='outer')
# 添加来源标记
result = pd.merge(left, right, on='key', how='outer', indicator=True)
join() – 基于索引合并
join() 主要是用来连接 DataFrame 的索引。它的功能类似于 merge(),但是 join() 默认是基于索引来合并数据。基本语法:
DataFrame.join(other, on=None, how='left', lsuffix='', rsuffix='', sort=False)
参数 | |
---|---|
other | 要连接的DataFrame、Series或DataFrame列表。 |
on | 用于合并的列,默认为 None,表示使用索引进行连接。 |
how | 连接方式。 ● ‘left’: 左连接,保留调用者的所有行(默认) ● ‘right’: 右连接 ● ‘outer’: 外连接 ● ‘inner’: 内连接 |
lsuffix | 左表重复列的后缀。 |
rsuffix | 右表重复列的后缀。 |
sort | 是否排序合并后的结果。 ● False:不排序(默认) ● True:排序 |
返回值 | 返回一个新的 DataFrame 或 Series |
使用示例:
import pandas as pd
left = pd.DataFrame({'A': ['A0', 'A1', 'A2']}, index=['K0', 'K1', 'K2'])
right = pd.DataFrame({'B': ['B0', 'B1', 'B3']}, index=['K0', 'K1', 'K3'])
# 默认左连接
result = left.join(right)
# 内连接
result = left.join(right, how='inner')
# 外连接
result = left.join(right, how='outer')
# 基于列连接(非索引)
result = left.join(right, on='key')
9. 排序
Pandas 提供了多种排序方法,可以对 Series 和 DataFrame 按索引或值进行排序。
sort_values() – 按值排序
sort_values() 用于按列的值进行排序。它可以对一个或多个列进行排序,可以选择升序或降序排列。基本语法:
DataFrame.sort_values(by, axis=0, ascending=True, inplace=False, kind='quicksort', na_position='last', ignore_index=False, key=None)
参数 | |
---|---|
by | DataFrame专用,指定排序依据的列名或列名列表。 |
axis | 排序方向。 ● 0 或 ‘index’: 按列值排序行(默认) ● 1 或 ‘columns’: 按行值排序列 |
ascending | 排序顺序。 ● True: 升序(默认) ● False: 降序 如果是多个列排序,可以传入一个布尔值列表,控制每列的排序方式。 |
inplace | 是否原地修改 ● False: 返回新对象(默认) ● True: 修改原对象 |
kind | 排序算法。‘quicksort’(默认), ‘mergesort’, ‘heapsort’, ‘stable’ |
na_position | 缺失值排序位置。 ● ‘last’: 缺失值放在最后(默认) ● ‘first’: 缺失值放在最前 |
ignore_index | 是否重置索引 ● False: 保留原索引(默认) ● True: 重置为0,1,2… |
key | 排序前应用于值的函数。 |
返回值 | 根据inplace值返回对应Series 或 DataFrame。 |
使用示例:
import pandas as pds = pd.Series([3, 1, 4, 2], index=['d', 'b', 'a', 'c'])
print(s.sort_values()) # 升序
print(s.sort_values(ascending=False)) # 降序df = pd.DataFrame({'A': [2, 1, 2, 3],'B': [1, 8, 4, 6],'C': ['x', 'y', 'z', 'w']
})
# 按单列排序
print(df.sort_values(by='B'))
# 按多列排序,不同排序顺序
print(df.sort_values(by=['A', 'B'], ascending=[True, False]))
# 使用 key 函数排序
print(df.sort_values(by='C', key=lambda x: x.str.upper()))
sort_index() – 按索引排序
sort_index() 用于Series 或 DataFrame按索引排序,而不是按列值排序。。基本语法:
DataFrame.sort_index(axis=0, level=None, ascending=True, inplace=False, kind='quicksort', na_position='last', ignore_index=False, key=None)
参数 | |
---|---|
axis | 排序方向。 ● 0 或 ‘index’: 排序行索引(默认) ● 1 或 ‘columns’: 排序列索引 |
level | 多层索引时指定排序级别 |
ascending | 排序顺序,默认为 True。 ● True:“升序排序。 ● False:降序排序。 |
inplace | 是否原地修改,默认为 False。 ● False:返回一个排序后的新的 DataFrame。 ● True:直接在原始数据上排序。 |
kind | 排序算法,默认为 ‘quicksort’,还可以选择 ‘mergesort’ 和 ‘heapsort’。 |
na_position | 缺失值排序位置。 ● ‘last’: 缺失值放在最后(默认) ● ‘first’: 缺失值放在最前 |
ignore_index | 是否重置索引 ● False: 保留原索引(默认) ● True: 重置为0,1,2… |
key | 排序前应用于值的函数。 |
返回值 | 根据inplace值返回对应Series 或 DataFrame。 |
使用示例:
import pandas as pds = pd.Series([1, 2, 3], index=['b', 'a', 'c'])
print(s.sort_index()) # 按索引升序
print(s.sort_index(ascending=False)) # 按索引降序df = pd.DataFrame({'A': [1, 2, 3],'B': [4, 5, 6]
}, index=['c', 'a', 'b'])
# 按行索引排序
print(df.sort_index())
# 按列索引排序
print(df.sort_index(axis=1))
10. 时间序列
Pandas 库中,处理时间数据是一个核心功能,特别是对于时间序列分析。Pandas 提供了专门的数据类型和一系列工具来处理时间和日期。
Pandas 时间类
Pandas 提供了几个核心类来处理时间数据:
- Timestamp:单个时间点(类似 Python datetime,但支持纳秒级精度)
- Timedelta:时间间隔(类似 Python timedelta,但支持纳秒级精度)
- Period:时间段(如 “2023年1月”)
- DatetimeIndex:时间索引(用于 DataFrame 或 Series 的索引)
- TimedeltaIndex:时间差索引
- PeriodIndex:时间段索引
Timestamp
Timestamp 是 Pandas 中表示单个时间点的基础类,相当于 Python datetime 的增强版,提供了更多功能和更高效的处理。在Python底层,Timestamp对象会被存储为NumPy的datetime64[ns]类型数据。
- 创建Timestamp对象
import pandas as pd
pd.Timestamp(ts_input, year=None, month=None, day=None, hour=None, minute=None, second=None, microsecond=None, nanosecond=None, tz=None, unit=None, freq=None, fold=None)
参数 | |
---|---|
ts_input | 时间数据,可以是日期时间字符串、时间戳、日期&时间组件 或 datetime 对象。 |
year | 指定时间戳的年份部分。 |
month | 指定时间戳的月份部分,整数类型,1到12。 |
day | 指定时间戳的日期部分。 |
hour | 指定时间戳的小时部分,整数类型,0到23。 |
minute | 指定时间戳的分钟部分,整数类型,0到59。 |
second | 指定时间戳的秒部分,整数类型,0到59。 |
microsecond | 指定时间戳的微秒部分,整数类型,0到999999。 |
nanosecond | 指定时间戳的纳秒部分,整数类型,0到999999999。 |
tz | 指定时间戳的时区,可以是字符串或时区对象。 |
unit | 当使用数字创建时间戳时,指定数字的单位,默认为 ‘ns’(纳秒)。 ● ‘s’:秒 ● ‘ms’:毫秒 ● ‘us’:微秒’ns’:纳秒(默认) |
freq | 用于指定时间频率,主要用于时间序列分析。 |
fold | 用于处理夏令时切换期间的模糊时间。 |
使用示例:
import pandas as pd
from datetime import datetime# 从字符串创建
ts1 = pd.Timestamp('2023-05-20')
ts2 = pd.Timestamp('2023-05-20 14:30:00')# 从datetime创建
ts3 = pd.Timestamp(datetime(2023, 5, 20))# 从Unix时间戳创建
ts4 = pd.Timestamp(1684567800, unit='s') # 单位可以是's','ms','us','ns'# 使用年、月、日、时、分等组件创建
ts5 = pd.Timestamp(year=2025, month=5, day=15, hour=14, minute=30)
- Timestamp属性
import pandas as pdts = pd.Timestamp("2023-05-20 14:30:00")
print(ts.year) # 2023
print(ts.month) # 5
print(ts.day) # 20
print(ts.hour) # 14
print(ts.minute) # 30
print(ts.second) # 0
print(ts.dayofweek) # 5(周六,0=周一)
print(ts.dayofyear) # 140(一年中的第140天)
- Timestamp常用方法
- now():获取当前时间的Timestamp对象
- strftime(format):将Timestamp对象化为字符串
- to_pydatetime() :将Timestamp对象转为 Python datetime
- to_datetime64() /to_numpy() :将Timestamp对象转为 numpy.datetime64
- replace():用于修改Timestamp对象特定部分(如年、月、日、时、分等)的方法,返回一个新的 Timestamp 对象
- to_period():将 Timestamp 转换为 Period
使用示例,在Python交互模式输出观察以下结果:
import pandas as pd# 获取当前时间
now = pd.Timestamp.now()# 时间格式化
now.strftime('%Y-%m-%d')# 类型转换
now.to_pydatetime() # 转为 Python datetime
now.to_datetime64() # 转为 numpy.datetime64
now.to_numpy() # 转为 numpy.datetime64(同上)# 替换部分时间
now.replace(hour=9, minute=0)# Timestamp 转换为 Period
ts = pd.Timestamp('2023-06-15 14:30:00')
period_month = ts.to_period('M') # 转换为月度周期
period_quarter = ts.to_period('Q') # 转换为季度周期
period_year = ts.to_period('Y') # 转换为年度周期
print(period_month,period_quarter,period_year) # 输出: 2023-06 2023Q2 2023
Timedelta
Timedelta 是 Pandas 中用于表示时间间隔或持续时间的类,类似于 Python 的 datetime.timedelta,但功能更强大且支持更高精度。在Python底层,Timedelta对象会被存储为NumPy的timedelta64[ns]类型数据。
- 创建Timedelta对象
import pandas as pd
pd.Timedelta(value,unit=None,**kwargs)
参数 | |
---|---|
value | 时间值(数值或字符串) |
unit | 如果输入是整数,则表示输入的单位。 ● ‘ns’:纳秒 ● ‘us’:微秒 ● ‘ms’:毫秒 ● ‘s’:秒 ● ‘m’:分 ● ‘h’:小 ● ‘D’:天 ● ‘W’:周 |
**kwargs | 其他参数(days,seconds,microseconds,milliseconds,minutes,hours,weeks) |
使用示例:
import pandas as pd# 通过字符串创建
td1 = pd.Timedelta('1 days 2 hours 3 minutes 4 seconds') # 基本格式
td2 = pd.Timedelta('1d 2h 3m 4s') # 简写格式
td3 = pd.Timedelta('5 days') # 仅天数
td4 = pd.Timedelta('1 days 02:03:04.000005') # 复杂格式# 使用日期时间组件
td5 = pd.Timedelta(days=1, hours=2, minutes=3, seconds=4)# 使用单位参数
td6 = pd.Timedelta(1.5, unit='days') # 1天半
td7 = pd.Timedelta(3600, unit='s') # 3600秒=1小时# 通过时间差计算创建
ts1 = pd.Timestamp('2023-01-01')
ts2 = pd.Timestamp('2023-01-03')
td8 = ts2 - ts1 # 2 days
- Timedelta属性
import pandas as pdtd = pd.Timedelta('1 days 2 hours 3 minutes 4.567890 seconds')
print(td.days) # 1 (整数天数部分)
print(td.seconds) # 7384 (2*3600 + 3*60 + 4 = 7384秒)
print(td.microseconds) # 567890 (微秒部分)
print(td.nanoseconds) # 0 (纳秒部分)
- Timedelta常用方法
- total_seconds():返回 Timedelta 对象表示的总秒数
import pandas as pdtd = pd.Timedelta('1 days 2 hours 3 minutes 4.567890 seconds')
print(td.total_seconds()) # 93784.56789 (总秒数)
Period
Period 是 Pandas 中用于表示时间段的类,它表示一个特定的时间区间(如某一天、某个月或某个季度),而不是像 Timestamp 那样的精确时间点。
- 创建Period对象
import pandas as pd
pd.Period(value=None, freq=None, ordinal=None, year=None, month=None,quarter=None, day=None, hour=None, minute=None, second=None)
参数 | |
---|---|
value | 时间值(字符串、datetime对象、Timestamp对象等) |
freq | 频率字符串(必须指定) ● ‘D’:日 ● ‘W’:周 ● ‘M’:月 ● ‘Q’:季 ● ‘Y’:年 ● ‘H’:小时 ● ‘min’:分钟 ● ‘S’:秒 |
ordinal | 周期序号(高级用法) |
year | 单独指定年 |
month | 单独指定月 |
quarter | 单独指定季度 |
day | 单独指定日 |
hour | 单独指定小时 |
minute | 单独指定分钟 |
second | 单独指定秒 |
使用示例:
import pandas as pd# 通过字符串和频率创建
p1 = pd.Period('2023-05-20', freq='D') # 创建日周期,表示2023年5月20日一整天
p2 = pd.Period('2023-05', freq='M') # 创建月周期,表示2023年5月整个月# 从datetime对象创建
dt = datetime(2023, 5, 20)
p4 = pd.Period(dt, freq='W') # 表示包含该日期的那一周# 从Timestamp对象创建
ts = pd.Timestamp('2023-05-20 14:30:00')
p5 = pd.Period(ts, freq='Q') # 表示包含该时间点的季度# 通过别指定年、月、日等时间创建
p6 = pd.Period(year=2023, month=5, day=20, freq='D')
p7 = pd.Period(year=2023, quarter=2, freq='Q') # 2023年第二季度
- Period属性
import pandas as pdp = pd.Period('2023-05', freq='M')print(p.year) # 2023
print(p.month) # 5
print(p.day) # 引发AttributeError(月周期没有day属性)
print(p.start_time) # 2023-05-01 00:00:00 (周期开始时间)
print(p.end_time) # 2023-05-31 23:59:59.999999999 (周期结束时间)
print(p.freq) # <MonthEnd> (频率对象)
- Period常用方法
- to_timestamp():将 Period 对象转换为 Timestamp 对象。可以选择转换为开始时间(how=‘start’)或结束时间(how=‘end’)。
- strftime(format)::将Period 对象化为字符串
import pandas as pdp = pd.Period('2023-05', freq='M')# 转换为时间戳
print(p.to_timestamp()) # 2023-05-01 00:00:00 (默认返回开始时间)
print(p.to_timestamp(how='end')) # 2023-05-31 23:59:59.999999999# 格式化输出
print(p.strftime('%Y-%m')) # '2023-05'
DatetimeIndex
DatetimeIndex 是由 Timestamp 对象组成的不可变索引,用于时间序列数据。
- 创建 DatetimeIndex 对象
import pandas as pd
pd.DatetimeIndex(data=None,freq=None,tz=None,normalize=False,closed=None,ambiguous='raise',dayfirst=False,yearfirst=False,dtype=None,copy=False,name=None)
参数 | |
---|---|
data | 传入的数据可以是日期、时间或日期时间格式的字符串、列表、数组,或者是其他类型的日期时间序列。 |
freq | 频率字符串。 ● ‘D’:按天 ● ‘B’:按工作日 ● ‘H’:按小时 ● ‘T’ 或 ‘min’:按分钟 ● ‘S’:按秒 ● ‘W’:按周 ● ‘M’:按月 ● ‘A’:按年 |
tz | 设置时区。可以使用时区字符串,例如 ‘UTC’、‘US/Eastern’ 等。如果没有指定时区,默认会使用系统的时区设置。 |
normalize | 是否标准化为午夜时间,默认值是 False。如果为 True,则所有的时间戳都会被规范化到午夜(00:00:00)。这通常用于处理时区转换或统一时间点。 |
closed | 区间闭合方式(‘left’或’right’) |
ambiguous | 处理模糊时间(夏令时转换) |
dayfirst | 如果为 True,日期字符串解析时会将日期部分放在前面(如:‘DD/MM/YYYY’ 格式)。默认值为 False(即 MM/DD/YYYY 格式)。 |
yearfirst | 如果为 True,日期字符串解析时会将年份部分放在前面(如:‘YYYY-MM-DD’ 格式)。默认值为 False。 |
dtype | 数据类型(通常自动推断) |
copy | 如果为 True,则在创建时会拷贝数据,而不是直接引用数据。默认值为 False。 |
name | 用于给索引命名的字符串。如果设置,DatetimeIndex 的名称将被显示在索引列头部。 |
使用示例:
import pandas as pd
from datetime import datetime# 使用字符串列表创建
dt_index0 = pd.DatetimeIndex(['2025-05-17', '2025-05-18', '2025-05-19'])
print(dt_index0)# 使用时间戳列表创建
dt_index1 = pd.DatetimeIndex([pd.Timestamp('2023-05-20'), pd.Timestamp('2023-05-21')])
print(dt_index1)# 使用datetime对象创建
dt_index2 = pd.DatetimeIndex([datetime(2023, 1, 1), datetime(2023, 1, 2), datetime(2023, 1, 3)])
print(dt_index2)
- DatetimeIndex属性
import pandas as pddt_index = pd.DatetimeIndex(['2025-05-17', '2025-05-18', '2025-05-19'])print(dt_index.year) # 年份数组
print(dt_index.month) # 月份数组
print(dt_index.day) # 日数组
print(dt_index.dayofweek) # 星期几(0=周一)
print(dt_index.is_leap_year) # 是否闰年
- DatetimeIndex常用方法
- to_period():将 DatetimeIndex 转换为 PeriodIndex
import pandas as pd# 创建时间序列
dates = pd.date_range('2023-01-01', periods=5, freq='ME')# 转换为月度周期
periods = dates.to_period('M')
print(periods)
# 输出: PeriodIndex(['2023-01', '2023-02', '2023-03', '2023-04', '2023-05'], dtype='period[M]')# 转换为季度周期
periods_q = dates.to_period('Q')
print(periods_q)
# 输出: PeriodIndex(['2023Q1', '2023Q1', '2023Q1', '2023Q2', '2023Q2'], dtype='period[Q-DEC]')
TimedeltaIndex
TimedeltaIndex 是 Pandas 中专门用于表示时间差(时间间隔)序列的索引类型,每个元素都是 Timedelta 对象。
- 创建TimedeltaIndex对象
import pandas as pd
pd.TimedeltaIndex(data=None,unit=None,freq=None,closed=None,dtype=None, copy=False, name=None)
参数 | |
---|---|
data | 传入的数据可以是时间差对象(Timedelta 类型的列表、数组或其他序列) |
unit | 单位。 ● ‘ns’:纳秒 ● ‘us’:微秒 ● ‘ms’:毫秒 ● ‘s’:秒 ● ‘m’:分钟 ● ‘h’:小时 ● ‘D’:天 |
freq | 时间差的频率。 ● ‘D’:按天 ● ‘H’:按小时 ● ‘T’ 或 ‘min’:按分钟 ● ‘S’:按秒 ● ‘L’:毫秒 ● ‘U’:微秒 ● ‘N’:纳秒 |
closed | 区间闭合方式(‘left’或’right’) |
dtype | 数据类型(通常自动推断) |
copy | 是如果为 True,则会拷贝数据。如果为 False,则直接引用数据。默认值为 False。 |
name | 设置索引的名称。可以指定字符串作为索引的名称。 |
import pandas as pd
import numpy as np# 从字符串列表创建
time_deltas = pd.TimedeltaIndex(['1 days', '2 days 3 hours', '0 days 12:30:00'])
print(time_deltas)# 从数值数组创建
td_index = pd.TimedeltaIndex([1, 2, 3], unit='D') # 1天, 2天, 3天
print(td_index)# 从timedelta64数组创建
arr = np.array([1, 2, 3], dtype='timedelta64[D]')
td_idx = pd.TimedeltaIndex(arr)
print(td_idx)
- TimedeltaIndex属性
import pandas as pdtd_index = pd.TimedeltaIndex(['1 days', '2 days 12:30:00'])
print(td_index.days) # 天数部分 [1, 2]
print(td_index.seconds) # 秒数部分 [0, 45000] (12*3600 + 30*60)
- TimedeltaIndex常用方法
- total_seconds():返回 TimedeltaIndex 对象表示的总秒数列表。
- to_pytimedelta():将 TimedeltaIndex 对象转换为Python timedelta对象列表
使用示例:
import pandas as pdtd_index = pd.TimedeltaIndex(['1 days', '2 days 12:30:00'])
print(td_index.total_seconds()) # 总秒数 [86400.0, 216000.0]
print(td_index.to_pytimedelta()) # [datetime.timedelta(days=1) datetime.timedelta(days=2, seconds=45000)]
PeriodIndex
PeriodIndex 是 Pandas 中用于表示时间段的索引类型,每个元素都是 Period 对象。
- 创建PeriodIndex对象
import pandas as pd
pd.PeriodIndex(data=None,freq=None,ordinal=None,copy=False,name=None,dtype=None)
参数 | |
---|---|
data | 输入数据,可以是 Period 对象的列表、datetime 对象的列表、字符串等。 |
freq | 时间段的频率,决定了时间段的粒度,这个参数在 data 为日期字符串或 datetime 对象时是必须的。常见的频率有: ● ‘D’:按日 ● ‘M’:按月 ● ‘Y’:按年 ● ‘H’:按小时 ● ‘min’:按分钟 ● ‘S’:按秒 |
ordinal | 周期序号(高级用法) |
copy | 是如果为 True,则会拷贝数据。如果为 False,则直接引用数据。默认值为 False。 |
name | 索引名称 |
dtype | 指定数据类型。通常,PeriodIndex 会自动推断数据类型,也可以显式指定类型。 |
使用示例:
import pandas as pd# 从字符串列表创建
periods = ['2023-01', '2023-02', '2023-03']
pi = pd.PeriodIndex(periods, freq='M')# 从 Period 对象列表创建
periods = [pd.Period('2023-01', freq='M'), pd.Period('2023-02', freq='M')]
pi = pd.PeriodIndex(periods)
- PeriodIndex属性
import pandas as pdperiods = ['2023-01', '2023-02', '2023-03']
pi = pd.PeriodIndex(periods, freq='M')print(pi.year) # 年份数组
print(pi.month) # 月份数组
print(pi.quarter) # 季度数组
print(pi.freq) # 频率对象
DateOffset
DateOffset 是 Pandas 中用于实现复杂日期偏移的核心类,提供了比简单频率字符串更灵活的时间偏移操作。
- 创建 DateOffset 对象
import pandas as pd
pd.DateOffset(n=1,normalize=False,years=0, months=0, weeks=0, days=0, hours=0, minutes=0, seconds=0, weekday=0)
参数 | |
---|---|
n | 偏移倍数(整数) |
years | 表示年份的偏移量,默认为 0。 |
months | 表示月份的偏移量,默认为 0。 |
days | 表示天数的偏移量,默认为 0。 |
weeks | 表示周的偏移量,默认为 0。 |
hours | 表示小时的偏移量,默认为 0。 |
minutes | 表示分钟的偏移量,默认为 0。 |
seconds | 表示秒数的偏移量,默认为 0。 |
weekday | 表示工作日的偏移量,可以使用 pd.DateOffset 来设置偏移到下一个工作日(例如,weekday=0 代表偏移到星期一)。 |
normalize | 布尔值。如果为 True,则返回的日期时间将标准化为午夜(00:00:00),即不包含具体的时分秒部分。 |
使用示例:
import pandas as pd
from pandas.tseries.offsets import DateOffset# 创建时间戳
ts = pd.Timestamp('2023-01-01 14:30:00')# 基本偏移
offset = DateOffset(days=5, hours=3)
print(ts + offset) # 2023-01-06 17:30:00# 使用n参数
offset = DateOffset(n=2, months=3)
print(ts + offset) # 2023-07-01 14:30:00
- DateOffset属性
from pandas.tseries.offsets import DateOffset# 创建复杂偏移
offset = DateOffset(years=1,months=2,days=3,hours=4,weekday=0, # 下周一normalize=True
)# 访问属性
print(offset.years) # 输出: 1
print(offset.months) # 输出: 2
print(offset.weekday) # 输出: 0
print(offset.normalize) # 输出: True
Pandas 时间方法
to_datetime()
to_datetime 是 pandas 中用来将字符串、数字或其他类型的数据转换为 datetime 对象(表现为pandas Timestamp 对象)的函数。
- 语法
import pandas as pd
pd.to_datetime(arg,errors='raise',dayfirst=False,yearfirst=False,utc=None,format=None,exact=True,unit=None,infer_datetime_format=False,origin='unix',cache=True)
参数 | |
---|---|
arg | 表示要转换的输入数据。可以是单个字符串或数字、字符串列表、Datetime 对象、DataFrame 或 Series 对象、日期或时间的 list 或 numpy 数组。 |
errors | 错误处理方式: ● ‘raise’(默认): 报错 ● ‘coerce’: 将无效解析设为NaT ● ‘ignore’: 返回原始输入 |
dayfirst | 布尔值。指定日期格式中是否将“日”放在前面(例如:DD/MM/YYYY)。默认是 False,表示“月”在前。 |
yearfirst | 布尔值,控制年份是否在最前面(例如:YYYY-MM-DD)。默认为 False,表示 MM-DD-YYYY 格式。 |
utc | 是否转换为UTC时间 |
format | 指定解析格式 |
exact | 是否严格匹配格式 |
unit | 数值输入的时间单位 |
infer_datetime_format | 是否尝试推断格式 |
origin | 数值输入的基准时间 |
cache | 是否缓存解析结果 |
返回值 | 返回 Timestamp、TimestampIndex 或 Series 对象,具体取决于输入。 |
使用示例:
import pandas as pd# 单一字符串转 datetime
date = pd.to_datetime('2025-05-19')
print(date)# 字符串列表转 datetime
dates = pd.to_datetime(['2025-05-19', '2025-06-20'])
print(dates)# Series对象转 datetime
dates = pd.to_datetime(pd.Series(['2023-05-20', '2023-05-21']))
print(dates)# 数值/数值数组(Unix时间戳) 转 datetime
dates = pd.to_datetime([1684567800, 1684654200], unit='s')
print(dates)# 从年月日各组成部分创建
dates =pd.to_datetime({"year":[2023], "month":[5], "day":[20]})
print(dates)# DataFrame对象 转 datetime
df = pd.DataFrame({'year': [2023, 2023],'month': [5, 6],'day': [20, 21]})
dates = pd.to_datetime(df)
print(dates)
- 应用
- 创建 Timestamp 对象
import pandas as pd# 创建一个 Timestamp 对象
datetime_obj = pd.to_datetime('2025-05-12 10:30:00')
print(type(datetime_obj)) # <class 'pandas._libs.tslibs.timestamps.Timestamp'>
- 创建 DatetimeIndex 对象
import pandas as pddates = pd.to_datetime(['2023-05-20', '2023-05-21', '2023-05-22'])
print(type(dates)) # <class 'pandas.core.indexes.datetimes.DatetimeIndex'>
- 时间序列分析
在时间序列分析中,经常将日期列设置为DataFrame的索引。
import pandas as pddata = {'value': [10, 20, 30]}
index = pd.to_datetime(['2023-05-20', '2023-05-21', '2023-05-22'])
ts = pd.DataFrame(data, index=index)
注意,DataFrame 列的 dtype 是 datetime64[ns],访问单个元素时返回的是 pd.Timestamp。
import pandas as pd# 创建一个 DataFrame,时间列为字符串
data = {'dates': ['2025-05-12 10:30:00', '2025-05-13 14:45:00']}
df = pd.DataFrame(data)# 转换为 datetime64[ns] 类型
df['dates'] = pd.to_datetime(df['dates'])# 查看列的数据类型
print(df['dates'].dtype) # 输出:datetime64[ns]# 查看列的第一个元素的类型
print(type(df['dates'][0])) # 输出:<class 'pandas._libs.tslibs.timestamps.Timestamp'>
to_timedelta()
to_timedelta() 是 Pandas 中用于将输入转换为Timedelta对象的函数,它能够处理多种格式的时间差数据。
- 语法
import pandas as pd
pd.to_timedelta(arg, unit='ns', errors='raise')
参数 | |
---|---|
arg | 输入数据,可以是以下形式之一: ● 时间差字符串 (如 ‘1 days 06:05:01.00003’) ● 数字序列 (如 [1, 2, 3]) ● 类似时间差的对象 ● pandas Timedelta 对象 ● pandas TimedeltaIndex 对象 |
unit | 当 arg 为数字时,指定时间单位。可选值包括: ● ‘W’ 或 ‘weeks’:周 ● ‘D’ 或 ‘days’:天 ● ‘h’ 或 ‘hours’:小时 ● ‘m’ 或 ‘minutes’:分钟 ● ‘s’ 或 ‘seconds’:秒 ● ‘ms’ 或 ‘milliseconds’:毫秒 ● ‘us’ 或 ‘microseconds’:微秒 ● ‘ns’ 或 ‘nanoseconds’:纳秒 |
errors | 指定错误处理方式: ● ‘raise’:遇到无效数据时引发异常 ● ‘coerce’:将无效数据转换为 NaT (Not a Time) ● ‘ignore’:遇到无效数据时返回输入 |
返回值 | 返回 Timedelta、TimedeltaIndex 或 Series 对象,具体取决于输入。 |
使用示例:
import pandas as pd# 从字符串创建 Timedelta
print(pd.to_timedelta('1 days 06:05:01.00003')) # 单个字符串
print(pd.to_timedelta(['1 days', '2 days', '3 days'])) # 多个字符串组成的列表# 从数字创建 Timedelta
print(pd.to_timedelta(1, unit='D')) # 单个数字
print(pd.to_timedelta([1, 2, 3], unit='D')) # 数字序列
- 应用
- 创建时间序列
import pandas as pddf = pd.DataFrame({'start_time': pd.to_datetime(['2023-01-01', '2023-01-02', '2023-01-03']),'duration': pd.to_timedelta([1, 2, 3], unit='D')
})
- 时间运算
import pandas as pd# 创建两个时间差
delta1 = pd.to_timedelta('2 days 3 hours')
delta2 = pd.to_timedelta('1 day 5 hours')# 加法
print(delta1 + delta2) # 3 days 08:00:00# 减法
print(delta1 - delta2) # 0 days 22:00:00# 乘法
print(delta1 * 2) # 4 days 06:00:00# 除法
print(delta1 / 2) # 1 days 01:30:00
date_range()
date_range() 是 Pandas 中用于生成固定频率日期时间索引的核心函数,在时间序列分析中非常常用。
- 语法
import pandas as pd
pd.date_range(start=None, end=None, periods=None, freq='D', tz=None, normalize=False, closed=None, **kwargs)
参数 | |
---|---|
start | 起始日期,可以是字符串(如 ‘2025-05-01’)、datetime 对象、Timestamp 对象等。 |
end | 结束日期,可以是字符串(如 ‘2025-05-01’)、datetime 对象、Timestamp 对象等。 |
periods | 要生成的周期数(整数),如果设置了 start 或 end,则可以使用 periods 来指定需要的时间数量。 |
freq | “时间间隔的频率,默认为 ‘D’(日)。可以是以下常见的频率: ● ‘D’ - 天 ● ‘B’ - 工作日 ● ‘H’ - 小时 ● ‘T’或’min’ - 分钟 ● ‘S’ - 秒 ● ‘L’或’ms’ - 毫秒 ● ‘U’或’us’ - 微秒 ● ‘N’ - 纳秒” |
tz | 时区名称(字符串或tzinfo对象) |
normalize | 将时间归一化为午夜(布尔值) |
name | 结果索引的名称(字符串) |
closed | “区间闭合方式(‘left’, 'right’或None),可设置为: ● ‘right’:右闭合(默认) ● ‘left’:左闭合 ● None:不闭合” |
返回值 | 返回一个DatetimeIndex对象,包含按指定频率生成的日期时间序列。 |
使用示例:
import pandas as pd# 指定开始和结束日期
print(pd.date_range(start='2023-01-01', end='2023-01-07'))
# 输出: DatetimeIndex(['2023-01-01', '2023-01-02', ..., '2023-01-07'], dtype='datetime64[ns]', freq='D')# 指定开始日期和周期数
print(pd.date_range(start='2023-01-01', periods=5))
# 输出: DatetimeIndex(['2023-01-01', '2023-01-02', ..., '2023-01-05'], dtype='datetime64[ns]', freq='D')# 指定结束日期和周期数
print(pd.date_range(end='2023-01-05', periods=5))
# 输出: DatetimeIndex(['2023-01-01', '2023-01-02', ..., '2023-01-05'], dtype='datetime64[ns]', freq='D')# 时间归一化(去除时分秒)
print(pd.date_range('2023-01-01 14:30', periods=3, normalize=True))
# 输出: 所有时间都变为00:00:00# 闭合区间控制
print(pd.date_range(start='2023-01-01', end='2023-01-03', closed='left'))
# 输出: 不包含end日期 ['2023-01-01', '2023-01-02']
- 应用
创建时间序列
# 创建时间序列数据
index = pd.date_range('2023-01-01', '2023-12-31', freq='D')
data = pd.DataFrame(index=index, data={'value': range(len(index))})# 创建工作日序列
bday_index = pd.date_range('2023-01-01', '2023-01-31', freq='B')
bday_series = pd.Series(1, index=bday_index)
print(bday_series.head())
timedelta_range()
timedelta_range() 是 Pandas 中用于生成固定频率时间差(Timedelta)序列的函数,常用于时间差相关的计算和分析。
import pandas as pd
pd.timedelta_range(start=None,end=None,periods=None,freq=None,name=None,closed=None)
参数 | |
---|---|
start | 起始时间差(字符串或Timedelta) |
end | 结束时间差(字符串或Timedelta) |
periods | 要生成的周期数(整数) |
freq | “时间差频率(字符串或DateOffset) ● ‘W’/‘weeks’ - 周 ● ‘D’/‘days’ - 天 ● ‘H’/‘hours’ - 小时 ● ‘T’/‘min’/‘minutes’ - 分钟 ● ‘S’/‘seconds’ - 秒 ● ‘L’/‘ms’/‘milliseconds’ - 毫秒 ● ‘U’/‘us’/‘microseconds’ - 微秒 ● ‘N’/‘ns’/‘nanoseconds’ - 纳秒” |
name | 结果索引的名称(字符串) |
closed | 区间闭合方式(‘left’, 'right’或None) |
返回值 | 返回一个TimedeltaIndex对象,包含按指定频率生成的时间差序列。 |
使用示例:
import pandas as pd# 指定开始和结束时间差
print(pd.timedelta_range(start='1 day', end='5 days'))
"""
TimedeltaIndex(['1 days', '2 days', '3 days', '4 days', '5 days'],dtype='timedelta64[ns]', freq='D')
"""# 指定开始时间差和周期数
print(pd.timedelta_range(start='1 hour', periods=4))
"""
TimedeltaIndex(['01:00:00', '02:00:00', '03:00:00', '04:00:00'],dtype='timedelta64[ns]', freq='H')
"""# 指定结束时间差和周期数
print(pd.timedelta_range(end='12 hours', periods=5, freq='3H'))
"""
TimedeltaIndex(['00:00:00', '03:00:00', '06:00:00', '09:00:00', '12:00:00'],dtype='timedelta64[ns]', freq='3H')
- 应用
时间序列数据偏移
import pandas as pd
base_date = pd.Timestamp('2023-01-01')
time_deltas = pd.timedelta_range(start='0 hours', periods=24, freq='h')# 创建24小时时间序列
time_series = base_date + time_deltas
print(time_series)
period_range()
period_range() 是 Pandas 中用于生成固定频率周期(Period)序列的函数,适用于需要处理时间区间(如整月、整季度)而非时间点的场景。
- 语法
import pandas as pd
pd.period_range(start=None,end=None,periods=None,freq=None,name=None)
参数 | |
---|---|
start | 起始周期(字符串或Period对象) |
end | 结束周期(字符串或Period对象) |
periods | 要生成的周期数(整数) |
freq | “指定生成的周期的频率,默认为 ‘D’(天)。可以使用以下常见的频率: ● ‘D’:天 ● ‘W’:周 ● ‘M’:月 ● ‘Q’:季度 ● ‘Y’:年” |
name | 表示生成的 PeriodIndex 的名称。可以用来为周期序列命名。 |
返回值 | 返回一个PeriodIndex对象,包含按指定频率生成的周期序列。 |
使用示例:
import pandas as pd# 指定开始和结束周期(月度)
print(pd.period_range(start='2023-01', end='2023-06', freq='M'))
"""
PeriodIndex(['2023-01', '2023-02', '2023-03', '2023-04', '2023-05', '2023-06'],dtype='period[M]')
"""# 指定开始周期和周期数(季度)
print(pd.period_range(start='2023Q1', periods=4, freq='Q'))
"""
PeriodIndex(['2023Q1', '2023Q2', '2023Q3', '2023Q4'],dtype='period[Q-DEC]')
"""# 指定结束周期和周期数(年度)
print(pd.period_range(end='2025', periods=3, freq='Y'))
"""
PeriodIndex(['2023', '2024', '2025'],dtype='period[A-DEC]')
"""
- 应用
创建周期序列
import pandas as pd# 生成2023年季度报表周期
quarters = pd.period_range(start='2023Q1', periods=4, freq='Q')
financial_data = pd.DataFrame(index=quarters, data={'revenue': [100, 120, 115, 130],'profit': [30, 35, 32, 38]})
print(financial_data)# 生成2023年月度周期
months = pd.period_range(start='2023-01', periods=12, freq='M')
sales = pd.Series([120, 150, 135, 160, 145, 180, 200, 175, 160, 190, 210, 230],index=months)
print(sales)
DataFrame/Series 时间方法
.dt
Series对象和DataFrame的列数据提供了dt属性接口,,专门用于操作包含日期时间或时间差(即dtype 为 datetime64[ns] 或 timedelta64[ns])的 Series 或 DataFrame 列,提供了一系列的日期时间操作属性和方法。
- 常见的 dt 属性有:
- year:年份
- month:月份
- day:日
- hour:小时
- minute:分钟
- second:秒
- microsecond:微秒
- nanosecond:纳秒
- date:返回日期部分
- time:返回时间部分
- dayofweek:星期几(0=周一,6=周日)
- day_of_week:同上(Pandas 1.1.0+)
- dayofyear:一年中的第几天
- day_of_year:同上
- quarter:季度
- is_month_start:是否月初
- is_month_end:是否月末
- is_quarter_start:是否季度初
- is_quarter_end:是否季度末
- is_year_start:是否年初
- is_year_end:是否年末
使用示例:
import pandas as pd# 创建一个包含日期时间数据的 DataFrame
data = {'date': pd.to_datetime(['2025-01-01', '2025-05-23', '2025-09-12'])}
df = pd.DataFrame(data)# 提取年份
df['year'] = df['date'].dt.year# 提取月份
df['month'] = df['date'].dt.month# 提取星期几
df['weekday'] = df['date'].dt.weekday# 提取日期
df['day'] = df['date'].dt.day# 获取星期几
df['dayofweek'] = df['date'].dt.dayofweek# 获取星期几
df['is_month_start'] = df['date'].dt.is_month_start# 输出结果
print(df)
- 常见的 dt 方法有:
- total_seconds():计算时间差的总秒数。
- strftime(format):将日期时间格式化为特定的字符串格式。
- to_period(freq):转换为周期对象。
- tz_convert(tz):时区转换。
- tz_localize(tz):设置时区。
使用示例:
import pandas as pdtd = pd.Series([pd.Timedelta(days=1, hours=6)])
print(td.dt.total_seconds()) # 输出: 108000.0dates = pd.Series(pd.date_range('2023-01-01', periods=3, freq='12H'))
print(dates.dt.strftime('%Y-%m-%d %A'))
# 输出:
# 0 2023-01-01 Sunday
# 1 2023-01-01 Sunday
# 2 2023-01-02 Monday
- 应用
- 提取节假日特征
import pandas as pd# 创建带日期列的DataFrame
df = pd.DataFrame({'date': pd.date_range('2023-01-01', periods=365)
})# 添加星期几和季度特征
df['weekday'] = df['date'].dt.dayofweek
df['quarter'] = df['date'].dt.quarter
- 计算营业时长
import pandas as pd# 计算时间差
operations = pd.DataFrame({'start': pd.to_datetime(['09:00:00', '13:30:00'], format='%H:%M:%S'),'end': pd.to_datetime(['12:00:00', '17:00:00'], format='%H:%M:%S')
})operations['duration'] = (operations['end'] - operations['start']).dt.total_seconds() / 3600
- 时间序列重采样
import pandas as pd
import numpy as np# 使用dt访问器筛选数据
sales = pd.DataFrame({'timestamp': pd.date_range('2023-01-01', periods=1000, freq='h'),'amount': np.random.randint(100, size=1000)
})# 筛选工作时间(9-18点)
work_hours = sales[sales['timestamp'].dt.hour.between(9, 18)]
asfreq()
asfreq() 方法是 Pandas 中用于转换时间序列频率的重要方法,主要存在于以下三类对象中:Period 、 PeriodIndex 对象和 Series(索引为 DatetimeIndex 时可用)。
- 语法
asfreq(freq, method=None, how=None, normalize=False, fill_value=None)
参数 | |
---|---|
freq | “目标频率(字符串或DateOffset),常见频率: ● ‘D’:日 ● ‘H’:小时 ● ‘M’:月 ● ‘Q’:季度 ● ‘A’:年” |
how | 周期转换方式(仅Period适用),值可以是:‘start’(期初)、‘end’(期末) |
method | “处理缺失值的方法,常见的值有: ● None:不填充(默认)。 ● pad’ ● bfill’:向后填充。” |
normalize | 是否将时间归一化到午夜 |
fill_value | 指定在缺失时填充的值。可以是常数、NaN |
使用示例
import pandas as pd# Period对象
p = pd.Period('2023-06', freq='M')
print(p.asfreq('Q')) # 转换为季度周期 → 输出: 2023Q2# PeriodIndex对象
pi = pd.period_range('2023-01', periods=3, freq='M')
print(pi.asfreq('Y')) # 转换为年度周期 → 输出: PeriodIndex(['2023','2023','2023'], dtype='period[Y-DEC]')
- 应用
- Period频率转换
import pandas as pd# 创建月度Period
p = pd.Period('2023-06', freq='M')# 转换为日频率(默认使用期末)
print(p.asfreq('D')) # 输出: 2023-06-30# 转换为日频率(指定期初)
print(p.asfreq('D', how='start')) # 输出: 2023-06-01# 转换为年度频率
print(p.asfreq('Y')) # 输出: 2023
- PeriodIndex频率转换
# 创建季度PeriodIndex
quarterly = pd.period_range('2023Q1', periods=4, freq='Q')# 转换为月度
print(quarterly.asfreq('M'))
"""
PeriodIndex(['2023-03', '2023-06', '2023-09', '2023-12'],dtype='period[M]')
"""# 转换为年度
print(quarterly.asfreq('Y'))
"""
PeriodIndex(['2023', '2023', '2023', '2023'],dtype='period[A-DEC]')
"""
- 时间序列重采样
# 创建日度数据
index = pd.date_range('2023-01-01', periods=5, freq='D')
ts = pd.Series([10, 20, 30, 40, 50], index=index)# 转换为2天频率(默认填充NaN)
print(ts.asfreq('2D'))
"""
2023-01-01 10.0
2023-01-03 30.0
2023-01-05 50.0
Freq: 2D, dtype: float64
"""# 使用前向填充
print(ts.asfreq('12h', method='ffill'))
"""
2023-01-01 00:00:00 10
2023-01-01 12:00:00 10
2023-01-02 00:00:00 20
...
Freq: 12H, dtype: int64
"""
resample()
resample()是Pandas中DataFrame/Series用于时间序列数据重新采样的一个方法。它既能实现降采样(减少数据点)也能实现升采样(增加数据点),通常配合各种聚合计算。
- 语法
DataFrame.resample(rule,axis=0,closed=None,label=None,convention='start',kind=None,on=None,level=None,origin='start_day',offset=None,group_keys=False)
参数 | |
---|---|
rule | 重采样频率,常见频率有: ● ‘D’:按天重采样 ● ‘W’:按周重采样 ● ‘M’:按月重采样 ● ‘Q’:按季度重采样 ● ‘A’:按年重采样 ● ‘H’:按小时重采样 ● ‘T’或’min’:按分钟重采样 ● ‘S’:按秒重采样 |
axis | 重采样轴,默认值为 0,表示沿着行进行操作。如果传递 1,则表示沿着列进行操作。 |
closed | 区间闭合方向,‘right’(右闭合)、‘left’(左闭合) |
label | 表示标签应放在区间的右端还是左端。可选值 ‘right’ 或 ‘left’ |
convention | 周期转换约定 |
kind | 用于指定重采样的类型,‘timestamp’ 返回 Timestamp,‘period’ 返回 Period。 |
on | 对于没有时间索引的DataFrame,指定重采样的列,该列必须是日期时间类型。 |
level | 如果数据是多层次索引(MultiIndex),则可以使用该参数指定重采样的层级。 |
origin | 决定重采样的起始点,可选值包括’epoch’和’start’。 |
offset | 用于指定时间偏移,输入字符串或 DateOffset |
group_keys | 布尔值,是否在聚合操作中包括 group 键。 |
返回值 | 返回一个 Resampler 对象,允许后续应用聚合操作或填充方法。 |
import pandas as pd
import numpy as np# 降采样(减少数据点)
index = pd.date_range('2023-01-01', periods=120, freq='min') # 创建分钟级数据
df = pd.DataFrame({'value': np.random.rand(120)}, index=index)
hourly = df.resample('h').mean() # 按小时求平均值
print(hourly.head())# 升采样(增加数据点)
daily = pd.DataFrame({'value': [1, 2, 3]},index=pd.date_range('2023-01-01', periods=3, freq='D')) # 创建日级数据
upsampled = daily.resample('6h').ffill() # 升采样到6小时,前向填充
print(upsampled)
- 应用
import pandas as pd
import numpy as np# 创建分钟级数据
index = pd.date_range('2023-01-01', periods=120, freq='min')
df = pd.DataFrame({'value': np.random.rand(120)}, index=index)# 同时计算多个统计量
result = df.resample('D').agg(['mean', 'max', 'min'])
print(result.head())# 按类别分组后重采样
df['category'] = ['A', 'B'] * 60
grouped = df.groupby('category').resample('h').mean()
print(grouped.head())# 使用自定义函数
def first_10_mean(x):return x['value'].head(10).mean()
custom = df.resample('6h').apply(first_10_mean)
print(custom.head())
shift()
shift() 是 Pandas 中用于在时间序列或数据框中移动数据,属于DataFrame/Series 对象 和 GroupBy 对象的一个方法。它可以将数据沿着指定的轴进行位移,并且通常用于处理时间序列数据,如计算变化率、滞后数据等。
- 语法
DataFrame.shift(periods=1, freq=None, axis=0, fill_value=None)
参数 | |
---|---|
periods | 移动的周期数。默认值是 1,表示移动一个单位。(正数向下/右,负数向上/左) |
freq | 用于时间序列的日期频率偏移。它允许你通过指定日期的频率来对时间数据进行移动,比如 ‘D’(天)、‘H’(小时)、‘M’(月)等。如果不提供该参数,则默认按行数移动。 |
axis | 指定沿哪个轴进行操作。0 表示沿着行移动(即按时间顺序移动),1 表示沿着列移动。 |
fill_value | 如果数据位移后存在缺失值,可以指定一个填充值来替代缺失的位置。 |
返回值 | 返回一个新的 DataFrame 或 Series。 |
使用示例:
import pandas as pd
import numpy as npdf = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6]})# 向下平移1行
print(df.shift(1))
"""A B
0 NaN NaN
1 1.0 4.0
2 2.0 5.0
"""# 向上平移1行
print(df.shift(-1))
"""A B
0 2.0 5.0
1 3.0 6.0
2 NaN NaN
"""# 时间序列平移(带频率)
ts = pd.Series([10, 20, 30], index=pd.date_range('2023-01-01', periods=3, freq='D'))
print(ts.shift(2, freq='D')) # 时间向前平移2天
"""
2023-01-03 10
2023-01-04 20
2023-01-05 30
Freq: D, dtype: int64
"""
- 应用
- 计算差值/变化率
# 计算日环比变化
ts = pd.Series([100, 110, 120, 115], index=pd.date_range('2023-01-01', periods=4, freq='D'))daily_change = (ts - ts.shift(1)) / ts.shift(1)
print(daily_change)
- 数据对齐
# 对齐两个时间序列(其中一个提前2天)
ts1 = pd.Series([1, 2, 3], index=pd.date_range('2023-01-01', periods=3))
ts2 = pd.Series([10, 20, 30], index=pd.date_range('2023-01-03', periods=3))aligned = ts1.shift(2, freq='D') + ts2 # 现在可以正确相加
11.文件操作
在 pandas 中,文件操作是非常常见的任务,主要用于读取和写入数据。pandas 提供了许多方法来读取和写入不同格式的文件,如 CSV、Excel、JSON、SQL 等。以下是 pandas 文件操作常用方法的语法、常用参数及示例。
read_csv() – 读取 csv 文件
基本语法:
pandas.read_csv(filepath_or_buffer, # 文件路径或 URLsep=',', # 分隔符,默认为逗号header='infer', # 行号作为列名,默认为0index_col=None, # 设置索引列usecols=None, # 读取指定列dtype=None, # 设置列的数据类型encoding='utf-8', # 文件编码names=None, # 自定义列名列表na_values=None, # 指定哪些值应被视为 NA/NaNnrows=None, # 读取的行数skiprows=None, # 跳过的行数na_values=None, # 设置缺失值parse_dates=False # 是否解析日期
)
使用示例:
import pandas as pd# 基本读取
df = pd.read_csv('data.csv')# 指定分隔符和编码
df = pd.read_csv('data.tsv', sep='\t', encoding='utf-8')# 指定索引列和自定义列名
df = pd.read_csv('data.csv', index_col='id', names=['id', 'name', 'age'])# 只读取前100行
df = pd.read_csv('large_data.csv', nrows=100)
to_csv() – 写入 csv 文件
基本语法:
pandas.read_csv(path_or_buf, # 文件路径sep=',', # 分隔符index=False, # 是否写入行索引header=True, # 是否写入列名columns=None, # 只写入指定列encoding='utf-8', # 文件编码float_format, # 浮点数格式date_format # 日期格式
)
使用示例:
import pandas as pd# 基本写入
df.to_csv('output.csv')# 不写入索引,指定分隔符
df.to_csv('output.tsv', index=False, sep='\t')# 只写入特定列
df.to_csv('output.csv', columns=['name', 'age'])# 指定浮点数格式
df.to_csv('output.csv', float_format='%.2f')df = pd.read_csv('output.csv', sep=',', header=0, index_col='ID', encoding='utf-8')
read_excel() – 读取 Excel 文件
基本语法:
pandas.read_excel(io, # 文件路径或 ExcelFile 对象sheet_name=0, # 要读取的工作表,可以是表名或索引header=0, # 用作列名的行号index_col=None, # 设置索引列usecols=None, # 选择读取的列dtype=None, # 设置列的数据类型engine=None, # Excel解析引擎,可以是openpyxl或xlrdna_values=None # 视为 NA 的值)
使用示例:
import pandas as pd# 读取第一个工作表
df = pd.read_excel('data.xlsx')# 读取特定工作表
df = pd.read_excel('data.xlsx', sheet_name='Sheet2')# 读取特定列范围
df = pd.read_excel('data.xlsx', usecols='A,C:E')# 读取多个工作表
dfs = pd.read_excel('data.xlsx', sheet_name=['Sheet1', 'Sheet2'])df = pd.read_excel('data.xlsx', sheet_name='Sheet1', header=0, index_col='ID')
to_excel() – 写入 Excel 文件
基本语法:
pandas.to_excel('output.xlsx', sheet_name='Sheet1', # 工作表名称index=False, # 是否写入行索引header=True, # 是否写入列名engine='openpyxl' # 指定 Excel 引擎)
使用示例:
import pandas as pd# 基本写入
df.to_excel('output.xlsx')# 指定工作表名称
df.to_excel('output.xlsx', sheet_name='Data')# 多个DataFrame写入不同工作表
with pd.ExcelWriter('output.xlsx') as writer:df1.to_excel(writer, sheet_name='Sheet1')df2.to_excel(writer, sheet_name='Sheet2')
read_json() – 读取 JSON 文件
基本语法:
pandas.read_json('file.json', orient='columns', # JSON 字符串的指示符('split','records','index','columns','values')(columns, index, records, split, etc.)dtype=None, # 设置列的数据类型convert_dates=True, # 是否转换为日期encoding='utf-8' # 文件编码
)
使用示例:
import pandas as pd# 从文件读取
df = pd.read_json('data.json')# 从JSON字符串读取
json_str = '{"name":{"0":"John","1":"Mary"},"age":{"0":25,"1":30}}'
df = pd.read_json(json_str)# 指定orient格式
df = pd.read_json(json_str, orient='index')
to_json() – 写入 JSON 文件
基本语法:
pandas.to_json(path_or_buf, # 文件路径orient='records', # JSON 的格式(columns, index, records, split, etc.)lines=False, # 是否将每行写成一个 JSON 对象index=False, # 是否写入索引date_format='iso', # 日期格式double_precision, #小数位数)
使用示例:
import pandas as pd
# 写入文件
df.to_json('output.json')# 指定orient格式
json_str = df.to_json('output.json', orient='records', index=False)
read_sql() – 读取 SQL 数据库
基本语法:
pandas.read_sql( sql, # SQL 查询字符串或表名con, # 数据库连接对象index_col, # 用作索引的列params # SQL 参数)
使用示例:
import pandas as pd
import sqlite3# 创建连接
conn = sqlite3.connect('database.db')# 从查询读取
df = pd.read_sql('SELECT * FROM table_name', conn)# 从表读取
df = pd.read_sql('table_name', conn)# 使用参数化查询
df = pd.read_sql('SELECT * FROM employees WHERE age > ?', conn, params=(30,))
to_sql() – 写入 SQL 数据库
基本语法:
pandas.to_sql(name, # 表名conn, # 数据库连接对象if_exists='fail', # 如果表存在的情况下,操作方式:'fail', 'replace', 'append'index=False, # 是否写入行索引index_label=None # 索引列名称)
使用示例:
import pandas as pd
import sqlite3# 创建连接
conn = sqlite3.connect('database.db')
# 基本写入
df.to_sql('table_name', conn)# 如果表存在则追加
df.to_sql('table_name', conn, if_exists='append')# 指定数据类型
from sqlalchemy.types import Integer, Text
dtypes = {'id': Integer(), 'name': Text()}
df.to_sql('table_name', conn, dtype=dtypes)
read_parquet() – 读取 Parquet 文件
基本语法:
pandas.read_parquet(path, # 文件路径columns, # 要读取的列engine # 使用的引擎('auto', 'pyarrow', 'fastparquet')
)
使用示例:
import pandas as pddf = pd.read_parquet('data.parquet')# 读取特定列
df = pd.read_parquet('data.parquet', columns=['id', 'name'])
to_parquet – 写入 Parquet 文件
基本语法:
pandas.to_parquet(path, # 文件路径engine, # 使用的引擎compression, # 压缩方式('snappy', 'gzip', 'brotli'等)index # 是否写入索引
)
使用示例:
import pandas as pddf.to_parquet('output.parquet')# 指定压缩方式
df.to_parquet('output.parquet', compression='gzip')