
在处理时间序列数据时,我们经常会遇到数据不连续或存在缺失日期行的情况。例如,某个类别(key)在特定日期没有记录,但我们希望为其补齐这些缺失的日期,并赋予默认值。本教程将提供一个专业且高效的解决方案,利用pandas的强大功能实现按组(key)填充缺失日期序列。
假设我们有一个Pandas DataFrame,其中包含日期(date)、类别(key)和数值(value)三列。某些key在某些日期可能没有数据记录。我们的目标是为每个key,在整个日期范围内(从最早日期到最晚日期),填充所有缺失的日期行,并为新生成的行设置默认值(例如,value为0)。
首先,我们创建示例数据:
import pandas as pd
data = {
'date': ['2023-12-01', '2023-12-03', '2023-12-04', '2023-12-01'],
'key': ['K0', 'K1', 'K0', 'K1'],
'value': [9, 3, 10, 8]
}
df = pd.DataFrame(data)
df['date'] = pd.to_datetime(df['date']) # 确保日期列为datetime类型
print("原始 DataFrame:")
print(df)输出的原始 DataFrame 如下:
date key value 0 2023-12-01 K0 9 1 2023-12-03 K1 3 2 2023-12-04 K0 10 3 2023-12-01 K1 8
我们可以看到,对于K0,缺失了2023-12-02和2023-12-03;对于K1,缺失了2023-12-02和2023-12-04。
解决此问题的核心在于:
我们将通过定义一个辅助函数并结合groupby().apply()来实现这一过程。
我们将创建一个名为fill_missing_dates的函数,该函数接收一个分组DataFrame (g) 以及整个数据集的最小日期 (min_date) 和最大日期 (max_date)。
def fill_missing_dates(g, min_date, max_date):
"""
为DataFrame分组填充缺失日期,并处理缺失值。
参数:
g (pd.DataFrame): 按'key'分组后的子DataFrame。
min_date (pd.Timestamp): 整个数据集的最小日期。
max_date (pd.Timestamp): 整个数据集的最大日期。
返回:
pd.DataFrame: 填充了缺失日期和值的子DataFrame。
"""
# 1. 生成完整的日期范围
full_date_range = pd.date_range(min_date, max_date)
# 2. 将日期列设置为索引,并使用完整日期范围进行reindex
# reindex操作会在full_date_range中存在但g中不存在的日期处插入NaN
g = g.set_index("date").reindex(full_date_range).reset_index()
# 3. 填充 'key' 列
# 对于新插入的行,'key' 列将是 NaN。
# 使用 ffill() (前向填充) 和 bfill() (后向填充) 确保 'key' 被正确传播。
# ffill() 处理大部分情况,bfill() 可以处理如果 reindex 导致开头有 NaN 的情况。
g["key"] = g["key"].ffill().bfill()
# 4. 填充 'value' 列
# 将缺失的 'value' 填充为 0,并转换回整数类型。
g["value"] = g["value"].fillna(0).astype(int)
# 重命名 'index' 列为 'date',因为 reindex().reset_index() 会将原索引命名为 'index'
g = g.rename(columns={'index': 'date'})
return g接下来,我们需要获取整个数据集的最小和最大日期,然后将fill_missing_dates函数应用到按key分组后的DataFrame上。
# 获取整个数据集的最小和最大日期
global_min_date = df["date"].min()
global_max_date = df["date"].max()
# 按 'key' 分组,并对每个分组应用填充函数
# group_keys=False 避免将分组键作为额外索引层添加到结果中
filled_df = df.groupby("key", group_keys=False).apply(
fill_missing_dates,
min_date=global_min_date,
max_date=global_max_date
)
print("\n填充后的 DataFrame:")
print(filled_df)输出的填充后 DataFrame:
date key value 0 2023-12-01 K0 9 1 2023-12-02 K0 0 2 2023-12-03 K0 0 3 2023-12-04 K0 10 0 2023-12-01 K1 8 1 2023-12-02 K1 0 2 2023-12-03 K1 3 3 2023-12-04 K1 0
可以看到,所有缺失的日期行都已成功补齐,并且value列被填充为0,key列也正确地传播到了新行。
将上述步骤整合到一起,得到完整的解决方案代码:
import pandas as pd
# 原始数据
data = {
'date': ['2023-12-01', '2023-12-03', '2023-12-04', '2023-12-01'],
'key': ['K0', 'K1', 'K0', 'K1'],
'value': [9, 3, 10, 8]
}
df = pd.DataFrame(data)
df['date'] = pd.to_datetime(df['date']) # 确保日期列为datetime类型
print("原始 DataFrame:")
print(df)
def fill_missing_dates(g, min_date, max_date):
"""
为DataFrame分组填充缺失日期,并处理缺失值。
"""
full_date_range = pd.date_range(min_date, max_date)
g = g.set_index("date").reindex(full_date_range).reset_index()
g["key"] = g["key"].ffill().bfill()
g["value"] = g["value"].fillna(0).astype(int)
g = g.rename(columns={'index': 'date'}) # 重命名回'date'
return g
# 获取整个数据集的最小和最大日期
global_min_date = df["date"].min()
global_max_date = df["date"].max()
# 按 'key' 分组,并对每个分组应用填充函数
filled_df = df.groupby("key", group_keys=False).apply(
fill_missing_dates,
min_date=global_min_date,
max_date=global_max_date
)
print("\n填充后的 DataFrame:")
print(filled_df)本教程提供了一种高效且灵活的方法,用于在Pandas DataFrame中按组填充缺失的日期序列。通过结合pd.date_range、DataFrame.reindex以及灵活的fillna策略,我们可以确保时间序列数据的完整性和一致性,这对于后续的数据分析、建模和可视化至关重要。理解并掌握这种数据预处理技术,将极大地提升你在处理时间序列数据时的效率和准确性。
以上就是Pandas DataFrame按组填充缺失日期序列的专业教程的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号