Python数据分析之Pandas

一、Pandas是什么

Pandas 是 Python 编程语言中一个开源的数据分析和处理库

二、核心数据结构

  • series:一维带标签的数组,可以存储任意数据类型(整数、浮点数、字符串等)。每个元素都有一个对应的索引(标签)。
  • DataFrame:二维表格型数据结构,类似于 Excel 表格或 SQL 数据表。它由行和列组成,每一列可以是不同的数据类型,并且拥有行索引和列标签。

[外链图片转存中…(img-Vil2k8nj-1774106817775)]

1、series数据结构

class Series(
data: Sequence[int | integer],
index: AxesData[Any] | None = None,
dtype: IntDtypeArg | UIntDtypeArg | None = None,
name: Hashable = None,
copy: bool | None = None
)

参数名称描述
data输入的数据(列表、整数、数组)
index索引,如果默认就是np.arrange(n),也可以自己定义
dtype表示的是数据值的类型
copy是否对data进行拷贝

(1)创建方法

import pandas as pd
s = pd.Series([1,2,3,4,5])
print(s)
# 0    1
# 1    2
# 2    3
# 3    4
# 4    5
# dtype: int64
s1 = pd.Series(5)
print(s1)

# 使用整数标量创建
s1 = pd.Series(5)
print(s1)
# 0    5
# dtype: int64

左边这一列是索引值,最后是元素的数据类型。

创建时索引值是可以自定义的,也可以用一个属性来描述数据是干什么用的

# 自定义索引
s = pd.Series([10, 2, 3, 4, 5], index=['A', 'B', 'C', 'D', 'E'])
print(s)
# A    10
# B     2
# C     3
# D     4
# E     5
# dtype: int64
# 描述数据用途
s = pd.Series([10, 2, 3, 4, 5], index=['A', 'B', 'C', 'D', 'E'], name='月份')
print(s)

通过字典来创建:

s = #通过字典来创建
s = pd.Series({"a":1, "b":2, "c":3, "d":4})
print(s)
s1 = pd.Series(s, index=["a", "c"])
print(s1)

(2)属性

分类属性名作用与返回值
基础信息values将 Series 的数据以 NumPy 数组的形式返回。
index返回 Series 的索引
dtype返回 Series 中元素的数据类型(如 int64, float64, object 等)。
shape返回 Series 的形状,由于是一维数据,所以是一个形如 (n,) 的元组,n 是元素个数。
size返回 Series 中元素的总个数。
ndim返回数据的维度数,Series 是一维的,所以永远是 1
命名与标识name返回或设置 Series 对象本身的名称。这在将多个 Series 组合成 DataFrame 时很有用。
index.name返回或设置 Series 索引的名称。
内存占用nbytes返回 Series 中所有数据占用的总字节数。
itemsize返回 Series 中每个元素占用的字节数。
状态检查empty判断 Series 是否为空,如果为空返回 True,否则返回 False
hasnans判断 Series 中是否包含缺失值 (NaN),如果包含返回 True,否则返回 False
特殊操作T返回 Series 的转置,由于 Series 是一维的,转置就是它本身

(3)访问数据

基于标签的显示索引访问:使用.loc[] 或直接使用 [] 操作符

s = pd.Series([10, 20, 30, 40], index = ['a', 'b', 'c', 'd'])
print(s['b'])
print(s.loc['c'])
print(s.loc['b':'d']) # 使用切片
print(s.loc[['a', 'c']]) #选取多个标签

基于标签的隐式索引访问:使用.iloc[]

print(s.iloc[1])
print(s.iloc[1: 3])# 位置1,2(不包含3),返回 Series
print(s.iloc[[0, 2]]) # 位置0和2

基于布尔Series筛选满足条件的元素:

# 选取大于20的元素
print(s[s > 20])     

# 结合多个条件
print(s[(s > 10) & (s < 40)])  

其他方法:

  • s.head(n):返回前 n 行(默认 5)。
  • s.tail(n):返回后 n 行。
  • s.sample(n):随机抽取 n 个样本。
  • s.take(indices):按位置索引选取,等价于 s.iloc[indices]
  • s.get(label, default):安全地获取标签对应的值,若不存在返回默认值。
print(s.head(2))       # 前两行
print(s.sample(2))     # 随机两行
print(s.get('x', 0))   # 标签 'x' 不存在,返回 0

(4)常用方法与统计

[外链图片转存中…(img-JpWC0t6w-1774106817777)]

[外链图片转存中…(img-0MLVsuWM-1774106817777)]

s = pd.Series([10, 2, np.nan, None, 3, 4, 5], index = ['a', 'b', 'c', 'd', 'e', 'f', 'g'])
print(s)
print(s.head()) # 默认取的是前5行的数据
print(s.head(3)) # 取前3行的数据
print(s.tail(5)) # 取后5行的数据
print(s.describe()) # 查看数值列的统计摘要
print(s.count()) # 获取元素个数
# 获取索引
print(s.keys()) # 方法
print(s.index) # 属性
# 判断是否是缺失值
print(s.isna()) 
# 检查是否包含在某一个参数集合里
print(s.isin([4]))
print(s.isin([4, 5, 6]))  # 用来检查每个元素是否在某一个列表中
# 计算相关的
print(s.mean()) # 计算平均数
print(s.std()) # 计算标准差
print(s.var()) # 方差
print(s.sum()) # 总和
print(s.max()) # 最大值
print(s.sort_values()) # 按值排序
print(s.sort_index()) # 按索引排序
print(s.quantile(0.25)) # 获取分位数
print(s.mode()) # 众数
print(s.value_counts()) # 值出现的次数
print(s.drop_duplicates()) # 去除重复项
print(s.unique()) # 去重
print(s.nunique()) # 去重后的元素个数

2、DataFrame数据结构

(1)DataFrame的创建

从字典创建的方式:字典的键成为列名,值成为列数据

import pandas as pd

data = {
    '姓名': ['张三', '李四', '王五'],
    '年龄': [25, 30, 28],
    '城市': ['北京', '上海', '广州']
}
df = pd.DataFrame(data)
print(df)

从二维列表创建的方式:每个内层列表对应一行

# 用二维列表的方式创建
data = [['张三', 25, '北京'],
        ['李四', 30, '上海'],
        ['王五', 28, '广州']]
df = pd.DataFrame(data, columns=['姓名', '年龄', '城市'])
print(df)

从numpy数组创建:

import numpy as np
arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
df = pd.DataFrame(arr, columns=['A', 'B', 'C'])
print(df)

从csv/excel文件读取:常用

# 读取 CSV 文件
df = pd.read_csv('data.csv')

# 读取 Excel 文件(需安装 openpyxl 或 xlrd)
df = pd.read_excel('data.xlsx', sheet_name='Sheet1')

(2)查看数据的基本信息

属性/方法作用
df.shape返回 (行数, 列数)
df.columns返回列索引
df.index返回行索引
df.dtypes每列数据类型
df.info()打印简要信息
df.describe()数值列统计摘要
df.head(n)前 n 行
df.tail(n)后 n 行
df.sample(n)随机抽取 n 行
df.isna()布尔型缺失值标记
df.dropna()删除含缺失值的行
df.fillna(value)填充缺失值
df.rename(columns=dict)重命名列
df.sort_values(by)按某列排序
df.reset_index(drop=True)重置索引
df.to_numpy()转换为 NumPy 数组
df = pd.DataFrame({
    '姓名': ['张三', '李四', '王五', '赵六'],
    '年龄': [25, 30, 28, 35],
    '城市': ['北京', '上海', '广州', '深圳'],
    '工资': [8000, 9000, 7500, 12000]
})

# 查看前几行(默认5行)
print(df.head(2))      # 前2行

# 查看后几行
print(df.tail(2))      # 后2行

# 查看基本信息(行列数、列类型、内存占用)
df.info()

# 查看描述性统计(数值列)
print(df.describe())

# 查看形状(行数, 列数)
print(df.shape)

# 查看列名
print(df.columns)

# 查看行索引
print(df.index)

# 查看数据类型的快速概览
print(df.dtypes)

(3)查看数据

通过列查看数据

# 选择单列,返回 Series
name_series = df['姓名']
print(type(name_series))

# 选择多列,返回 DataFrame
sub_df = df[['姓名', '年龄']]
print(sub_df)

通过行查看数据(跟上述series一样分为显式索引**loc()和隐式索引iloc()**两种方式)注意:loc 切片包含两端!

# 使用 iloc 按整数位置选择行(类似 NumPy)
row_0 = df.iloc[0]          # 第一行,返回 Series
rows_1_2 = df.iloc[1:3]     # 第二行和第三行,返回 DataFrame

# 使用 loc 按标签索引选择行(如果索引不是默认整数,需指定)
row_0_label = df.loc[0]
rows_1_2_label = df.loc[1:2]   # 注意:loc 切片包含两端!

同时选择行和列

# 使用 loc:df.loc[行条件, 列名]
# 选择第0行到第2行的 '姓名' 和 '年龄' 列
df.loc[0:2, ['姓名', '年龄']]

# 使用 iloc:df.iloc[行位置, 列位置]
# 选择前3行,前2列
df.iloc[0:3, 0:2]

# 选择特定单元格
value = df.loc[1, '年龄']      # 第2行的年龄
value = df.iloc[2, 1]          # 第3行第2列

布尔索引

# 筛选出年龄大于28的行
df[df['年龄'] > 28]

# 多条件:年龄大于28且城市为'上海'
df[(df['年龄'] > 28) & (df['城市'] == '上海')]

# 使用 isin 筛选城市为'北京'或'广州'的行
df[df['城市'].isin(['北京', '广州'])]

添加新列

# 直接赋值,长度必须与行数一致
df['性别'] = ['男', '女', '男', '女']

# 基于现有列计算新列
df['年薪'] = df['工资'] * 12

# 使用 assign 方法(返回新 DataFrame,不修改原数据)
df_new = df.assign(税后工资=df['工资'] * 0.9)

(4)基本操作

删除列

# 删除列(axis=1),默认返回新 DataFrame
df_dropped = df.drop('性别', axis=1)

# 原地删除
df.drop('性别', axis=1, inplace=True)

# 删除多列
df.drop(['年薪', '工资'], axis=1, inplace=True)

重命名

df.rename(columns = {'姓名': 'name', '年龄': 'age'}, inplace = True)

缺失值初步处理

# 检查是否有缺失值
print(df.isna().sum())        # 每列缺失值个数

# 删除包含缺失值的行
df_clean = df.dropna()

# 填充缺失值
df_filled = df.fillna(0)      # 用0填充
df['年龄'].fillna(df['年龄'].mean(), inplace=True)  # 用均值填充某一列

排序

# 按年龄升序排序
df_sorted = df.sort_values('年龄')

# 按年龄降序,年龄相同则按工资降序
df_sorted = df.sort_values(['年龄', '工资'], ascending=[False, False])

重置索引

# 在筛选或排序后,索引可能混乱,可以重置为默认整数索引
df.reset_index(drop=True, inplace=True)   # drop=True 丢弃原索引

与Series的相互转换:

​ 从DataFrame中取一列得到Series

s = df['姓名']      # 返回 Series

​ 将多个Series组合成DataFrame

s1 = pd.Series([1,2,3], name='A')
s2 = pd.Series([4,5,6], name='B')
df = pd.concat([s1, s2], axis=1)   # 按列拼接
# 或者直接用字典
df = pd.DataFrame({'A': s1, 'B': s2})

​ DataFrame 转 NumPy 数组

arr = df.to_numpy()   # 返回 ndarray,不包含索引和列名

三、数据清洗与预处理

1、处理缺失值

识别缺失值

import pandas as pd
import numpy as np

df = pd.DataFrame({
    '姓名': ['张三', '李四', '王五', '赵六'],
    '年龄': [25, np.nan, 28, 35],
    '城市': ['北京', '上海', None, '深圳'],
    '工资': [8000, 9000, 7500, np.nan]
})

# 检查每个元素是否为缺失值
print(df.isna())          # 返回布尔型DataFrame
print(df.isnull())        # 等价于 isna()

# 统计每列缺失值个数
print(df.isna().sum())

# 统计总缺失值个数
print(df.isna().sum().sum())

删除缺失值

# 删除包含任何缺失值的行(默认 axis=0)
df_clean = df.dropna()

# 删除全是缺失值的行
df.dropna(how='all')

# 删除至少包含3个缺失值的行
df.dropna(thresh=3)

# 删除包含缺失值的列
df.dropna(axis=1)

填充缺失值

# 用固定值填充
df_filled = df.fillna(0)

# 用列均值填充数值列
df['年龄'] = df['年龄'].fillna(df['年龄'].mean())

# 用前一个值填充(向前填充)
df.fillna(method = 'ffill')

# 用后一个值填充
df.fillna(method = 'bfill')

# 对不同列指定不同的填充值
df.fillna({'年龄': 30, '城市': '未知', '工资': 5000})

# 插值法填充(适用于线性趋势)
df.interpolate()

2、处理重复值

识别重复行

df = pd.DataFrame({
    '姓名': ['张三', '李四', '王五', '李四'],
    '年龄': [25, 30, 28, 30],
    '城市': ['北京', '上海', '广州', '上海']
})

# 判断哪些行完全重复(返回布尔Series)
print(df.duplicated())

# 基于某些列判断重复
print(df.duplicated(subset=['姓名', '年龄']))

# 保留第一次出现(默认)
print(df.duplicated(keep='first'))

删除重复行

# 删除完全重复的行(保留第一次出现的)
df_clean = df.drop_duplicates()

# 基于某些列删除重复
df_clean = df.drop_duplicates(subset=['姓名', '年龄'])

# 保留最后一次出现
df_clean = df.drop_duplicates(keep='last')

3、数据类型转换

查看数据类型

print(df.dtypes)

类型转换

# 将列转换为整数(如果可能)
df['年龄'] = df['年龄'].astype(int)

# 转换为字符串
df['城市'] = df['城市'].astype(str)

# 转换为类别类型(节省内存)
df['城市'] = df['城市'].astype('category')

安全转换数值类型

errors 参数:‘raise’(报错),‘coerce’(转为NaN),‘ignore’(不转换)

# 将含有非数字的列强制转换为数值,无法转换的变为 NaN
df['工资'] = pd.to_numeric(df['工资'], errors='coerce')

日期时间转换

df = pd.DataFrame({
    '日期': ['2023-01-01', '2023/02/15', '2023-03-20 10:30:00'],
    '销售额': [100, 200, 150]
})
df['日期'] = pd.to_datetime(df['日期']format = 'mixed')
print(df['日期'].dt.year)   # 提取年份

4、字符串处理

大小写转换

df['城市'] = df['城市'].str.lower()    # 转小写
df['城市'] = df['城市'].str.upper()    # 转大写
df['城市'] = df['城市'].str.title()    # 每个单词首字母大写

去除空白字符串

df['城市'] = df['城市'].str.strip()       # 去除首尾空格
df['城市'] = df['城市'].str.lstrip()      # 去除左侧空格
df['城市'] = df['城市'].str.rstrip()      # 去除右侧空格

字符串替换

df['城市'] = df['城市'].str.replace('京', '北京')

分割和提取

# 按分隔符分割成列表
df['城市_拆分'] = df['城市'].str.split(' ')

# 分割后取出第一部分
df['城市_首部分'] = df['城市'].str.split(' ').str[0]

# 提取指定位置的字符
df['手机号'] = df['手机号'].str[0:3]   # 前三位

判断包含

df['是否含北京'] = df['城市'].str.contains('北京')

5、应用函数

(1)对行或列应用函数

# 对列应用(默认 axis=0)
df['工资_税收后'] = df['工资'].apply(lambda x: x * 0.9)

# 对行应用(axis=1),需访问多列
def calculate_total(row):
    return row['工资'] * 12 + row['奖金']   
df['年收入'] = df.apply(calculate_total, axis=1)

(2)替换Series中的值默认不在映射中的值变为 NaN

# 映射字典
city_mapping = {'北京': 'BJ', '上海': 'SH', '广州': 'GZ'}
df['城市代码'] = df['城市'].map(city_mapping)

(3)对DataFrame中的每个元素应用函数

# 将每个数值保留两位小数
df = df.applymap(lambda x: round(x, 2) if isinstance(x, (int, float)) else x)

6、异常值的检测与处理

(1)基于统计的处理方法

# 假设年龄列,找出超过3个标准差的值
mean_age = df['年龄'].mean()
std_age = df['年龄'].std()
lower = mean_age - 3 * std_age
upper = mean_age + 3 * std_age
outliers = df[(df['年龄'] < lower) | (df['年龄'] > upper)]

(2)箱线图法

Q1 = df['工资'].quantile(0.25)
Q3 = df['工资'].quantile(0.75)
IQR = Q3 - Q1
lower = Q1 - 1.5 * IQR
upper = Q3 + 1.5 * IQR
outliers = df[(df['工资'] < lower) | (df['工资'] > upper)]

(3)处理异常值

# 方法1:删除异常值所在行
df_clean = df[(df['工资'] >= lower) & (df['工资'] <= upper)]

# 方法2:替换为边界值(截尾)
df['工资'] = df['工资'].clip(lower=lower, upper=upper)

# 方法3:替换为均值/中位数
median = df['工资'].median()
df.loc[df['工资'] > upper, '工资'] = median

7、数据标准化/归一化

from sklearn.preprocessing import StandardScaler, MinMaxScaler

# Z-score 标准化
scaler = StandardScaler()
df_scaled = scaler.fit_transform(df[['年龄', '工资']])

# 最小-最大归一化
scaler = MinMaxScaler()
df_normalized = scaler.fit_transform(df[['年龄', '工资']])

四、基本分组与聚合

df = pd.DataFrame({
    '部门': ['销售', '销售', '技术', '技术', '技术', '销售'],
    '姓名': ['张三', '李四', '王五', '赵六', '孙七', '周八'],
    '性别': ['男', '女', '男', '女', '男', '女'],
    '工资': [8000, 7500, 9000, 8500, 9500, 7200],
    '绩效': [85, 90, 88, 92, 95, 82]
})
print(df)

(1)按单列分组,计算某列的均值

# 按部门分组,计算工资均值
grouped = df.groupby('部门')['工资'].mean()
print(grouped)

(2)按单列分组,同时聚合多列

# 按部门分组,计算工资和绩效的均值
result = df.groupby('部门')[['工资', '绩效']].mean()
print(result)

(3)按多列分组

# 按部门和性别分组,计算工资均值
result = df.groupby(['部门', '性别'])['工资'].mean()
print(result)

(4)使用 agg() 进行灵活聚合

# 对同一列应用多个聚合函数,按部门分组计算工资的均值、最小值、最大值
result = df.groupby('部门')['工资'].agg(['mean', 'min', 'max'])
print(result)
# 对不同列应用不同聚合函数
result = df.groupby('部门').agg({
    '工资': ['mean', 'max'],
    '绩效': 'median'
})
print(result)
# 定义一个函数:计算工资的范围(max-min)
def range_func(x):
    return x.max() - x.min()

result = df.groupby('部门')['工资'].agg(range_func)
# 或者使用 lambda
result = df.groupby('部门')['工资'].agg(lambda x: x.max() - x.min())

(5)转换transform

可以对每个分组进行运算,但返回一个与原 DataFrame 形状相同的结果

# 给每个部门增加一列,表示该部门的平均工资
df['部门平均工资'] = df.groupby('部门')['工资'].transform('mean')
print(df)

(6)过滤filter

根据分组的某些条件筛选组,保留满足条件的整个组。

# 只保留平均工资高于8000的部门
filtered = df.groupby('部门').filter(lambda x: x['工资'].mean() > 8000)
print(filtered)

五、pandas合并与拼接

方法适用场景关键参数
concat简单的行/列拼接(无键对齐)axis, join, ignore_index
merge基于列的数据库风格连接on, how, left_on, right_on
join基于索引的连接(简便)on, how
import pandas as pd

# 员工基础信息表
df1 = pd.DataFrame({
    '员工ID': [101, 102, 103, 104],
    '姓名': ['张三', '李四', '王五', '赵六'],
    '部门': ['销售', '技术', '销售', '技术']
})

# 员工工资表
df2 = pd.DataFrame({
    '员工ID': [101, 102, 103, 105],
    '工资': [8000, 9000, 7500, 8500],
    '绩效': [85, 92, 88, 90]
})

# 部门奖金表
df3 = pd.DataFrame({
    '部门': ['销售', '技术'],
    '奖金': [2000, 3000]
})

print("df1 (员工基础信息):\n", df1)
print("\ndf2 (员工工资):\n", df2)
print("\ndf3 (部门奖金):\n", df3)

1、沿着轴拼接pd.concat()

(1)垂直拼接,会增加行

# 假设有更多员工数据
df4 = pd.DataFrame({
    '员工ID': [106, 107],
    '姓名': ['孙七', '周八'],
    '部门': ['产品', '市场']
})

# 垂直拼接(axis=0,默认)
df_combined = pd.concat([df1, df4], ignore_index=True)  # ignore_index 重置索引
print(df_combined)

(2)水平拼接,会增加列

# 水平拼接,要求行索引对齐
df_horizontal = pd.concat([df1, df2], axis=1)
print(df_horizontal)  # 注意:行索引没有对齐,可能产生 NaN

(3)使用 join 参数控制对齐方式

  • join='outer'(默认):取并集,缺失部分填充 NaN。
  • join='inner':取交集,只保留两个 DataFrame 都有的行索引。
# 设置员工ID为索引,然后水平拼接
df1_indexed = df1.set_index('员工ID')
df2_indexed = df2.set_index('员工ID')
concat_inner = pd.concat([df1_indexed, df2_indexed], axis=1, join='inner')
print(concat_inner)

2、数据的拼接pd.merge()

merge 类似于 SQL 的 JOIN,根据一个或多个键将两个 DataFrame 的行连接起来。这是最常用的合并方式。

(1)inner join:只保留两个表都存在的键

merged_inner = pd.merge(df1, df2, on='员工ID', how='inner')
print(merged_inner)

(2)left join:只保留左表中的所有行

merged_left = pd.merge(df1, df2, on='员工ID', how='left')
print(merged_left)

(3)right join:只保留右表中的所有行

merged_right = pd.merge(df1, df2, on='员工ID', how='right')
print(merged_right)

(4)outer join:保留两表中的所有行,缺失部分用NAN填充

merged_right = pd.merge(df1, df2, on='员工ID', how='right')
print(merged_right)

(5)按多个键合并

# 先创建两个表,都有多个共同列
df_left = pd.DataFrame({
    '部门': ['销售', '技术', '销售'],
    '姓名': ['张三', '李四', '王五'],
    '工资': [8000, 9000, 7500]
})
df_right = pd.DataFrame({
    '部门': ['销售', '技术'],
    '奖金': [2000, 3000]
})
merged_multi = pd.merge(df_left, df_right, on='部门', how='left')
print(merged_multi)

(6)当两表键名不同时,使用 left_onright_on

# df1 的键是 '员工ID',df2 的键是 'ID'
df2_renamed = df2.rename(columns={'员工ID': 'ID'})
merged_diff = pd.merge(df1, df2_renamed, left_on='员工ID', right_on='ID', how='inner')
print(merged_diff)

3、基于索引的合并join(),先设置索引

join 是 DataFrame 的方法,默认基于索引进行合并,相当于 merge 的简化版。常用于索引对齐。

(1)左连接

# 将 df2 的索引设为员工ID,然后与 df1 基于索引合并
df1_indexed = df1.set_index('员工ID')
df2_indexed = df2.set_index('员工ID')
joined = df1_indexed.join(df2_indexed, how='left')
print(joined)

(2)指定列与索引合并

joined_on = df1.join(df2_indexed, on='员工ID', how='left')
print(joined_on)

六、时间序列

1、时间戳索引

import pandas as pd

# 创建包含日期字符串的 DataFrame
df = pd.DataFrame({
    '日期': ['2023-01-01', '2023-01-02', '2023-01-05'],
    '销售额': [100, 200, 150]
})

# 将日期列转为 datetime 类型
df['日期'] = pd.to_datetime(df['日期'])

# 设置为索引
df.set_index('日期', inplace=True)
print(df)

(1)创建日期范围pd.data_range

常见频率

‘D’:日,‘B’:工作日,‘H’:小时,‘T’/‘min’:分钟,‘S’:秒,‘M’:月末,‘MS’:月初

# 生成连续日期
date_index = pd.date_range(start='2023-01-01', end='2023-01-10', freq='D')
print(date_index)

(2)使用日期范围创建时间序列

dates = pd.date_range('2023-01-01', periods=100, freq='D')
ts = pd.Series(range(100), index=dates)
print(ts.head())

2、时间序列的索引与切片

(1)基于标签索引

# 选取单日
print(ts['2023-01-05'])

# 切片:选取某段时间
print(ts['2023-01-05':'2023-01-10'])

3、重采样

(1)降采样

# 按周汇总,计算每周的总销售额
weekly = ts.resample('W').sum()
print(weekly.head())

# 按月计算平均值
monthly = ts.resample('M').mean()
print(monthly)

(2)升采样

# 从日数据升采样到小时,填充方法可选
hourly = ts.resample('H').ffill()  # 向前填充
print(hourly.head())

4、移动窗口与滚动计算

(1)滚动窗口

# 计算7日移动平均
rolling_mean = ts.rolling(window=7).mean()
print(rolling_mean.head(10))

(2)扩展窗口

# 计算7日移动平均
rolling_mean = ts.rolling(window=7).mean()
print(rolling_mean.head(10))

索引与切片

(1)基于标签索引

# 选取单日
print(ts['2023-01-05'])

# 切片:选取某段时间
print(ts['2023-01-05':'2023-01-10'])

3、重采样

(1)降采样

# 按周汇总,计算每周的总销售额
weekly = ts.resample('W').sum()
print(weekly.head())

# 按月计算平均值
monthly = ts.resample('M').mean()
print(monthly)

(2)升采样

# 从日数据升采样到小时,填充方法可选
hourly = ts.resample('H').ffill()  # 向前填充
print(hourly.head())

4、移动窗口与滚动计算

(1)滚动窗口

# 计算7日移动平均
rolling_mean = ts.rolling(window=7).mean()
print(rolling_mean.head(10))

(2)扩展窗口

# 计算7日移动平均
rolling_mean = ts.rolling(window=7).mean()
print(rolling_mean.head(10))
Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐