
在数据分析中,我们经常会遇到需要根据特定条件对数据进行动态聚合的场景。例如,在一个包含多个日期列和一行特定日期列的dataframe中,我们可能需要计算每个实体在指定日期之前和之后所有数值的总和。本教程将详细阐述如何利用pandas的强大功能,高效地完成这一任务。
假设我们有一个DataFrame,其中包含一个标识符列(如Code)、一个指定日期列(Date),以及一系列以日期命名的数值列。我们的目标是为每一行计算:
为了便于演示,我们首先创建一个示例DataFrame:
import pandas as pd
import numpy as np
# 创建示例数据
data = {
'Code': ['12345', '12346', '12347'],
'202001': [1000, 999, 1983],
'202002': [1001, 1000, 1984],
'202003': [1002, 1001, 1985],
'202004': [1003, 1002, 1986],
'202005': [1004, 1003, 1987],
'202006': [1005, 1003, 1988],
'202007': [3006, 1005, 1989],
'202008': [1007, 1006, 1990],
'202009': [1008, 1007, 1991],
'202010': [1009, 1008, 1992],
'202011': [1010, 1009, 1993],
'202012': [1011, 1010, 1994],
'Date': ['202004', '202006', '202010']
}
df = pd.DataFrame(data)
print("原始DataFrame:")
print(df)我们将通过以下几个关键步骤来实现数据的动态聚合:
原始DataFrame是宽格式的,日期列作为列名。为了方便与Date列进行比较和聚合,我们需要将其转换为长格式。pd.melt()函数可以将指定的列作为标识符变量,其余列作为值变量,并将列名转换为新的变量列。
# 标识符列:'Code', 'Date'
# 值列:所有日期列
tmp = df.melt(id_vars=['Code', 'Date'])
print("\n经过melt操作后的DataFrame (tmp):")
print(tmp.head())tmp DataFrame现在包含 Code、Date、variable(原日期列名)和 value(对应数值)四列。
为了正确比较日期,我们需要确保Date列和variable列(它们现在都是字符串)的数据类型是可比较的。尽管它们是字符串,但如果格式一致(如'YYYYMM'),可以直接进行字符串比较。然后,我们将使用np.where()结合gt()(greater than)来判断每个variable日期是早于还是晚于其对应行的Date。
# 确保'Date'和'variable'列为字符串类型,以便进行比较
tmp = tmp.astype({'Date': str, 'variable': str})
# 创建新列'col',标记值是'Before'还是'After'指定日期
# 注意:这里'Before'包含等于指定日期的情况,'After'不包含
tmp['col'] = np.where(tmp['Date'].gt(tmp['variable']), 'Before', 'After')
print("\n添加'col'列后的DataFrame (tmp):")
print(tmp.head())这里,tmp['Date'].gt(tmp['variable']) 比较的是字符串大小,对于'YYYYMM'格式的日期字符串,这等同于日期比较。如果Date晚于variable,则variable属于Before,否则属于After。
现在,我们可以根据Code和新创建的col列('Before'或'After')进行分组,并对value列求和。
# 按Code和col分组,并对value求和
grouped_sums = tmp.groupby(['Code', 'col'])['value'].sum()
print("\n分组求和后的Series (grouped_sums):")
print(grouped_sums.head())结果是一个MultiIndex Series。
为了将'Before'和'After'作为独立的列,我们需要使用unstack('col')。
# 将'col'的索引层转为列
unstacked_sums = grouped_sums.unstack('col')
print("\nunstack后的DataFrame (unstacked_sums):")
print(unstacked_sums.head())此时,unstacked_sums DataFrame的索引是Code,列是Before和After。为了保持与原DataFrame的列顺序一致,可以进行列重排。
# 确保'Before'和'After'列的顺序
unstacked_sums = unstacked_sums[['Before', 'After']]
print("\n重排列顺序后的DataFrame (unstacked_sums):")
print(unstacked_sums.head())最后一步是将计算出的Before和After总和合并回原始的df DataFrame。我们使用left_on='Code'和right_index=True,因为unstacked_sums的索引就是Code。
# 将计算结果合并回原始DataFrame
out = df.merge(unstacked_sums, left_on='Code', right_index=True, how='left')
print("\n最终结果DataFrame:")
print(out)将上述所有步骤整合,完整的解决方案代码如下:
import pandas as pd
import numpy as np
# 1. 创建示例数据
data = {
'Code': ['12345', '12346', '12347'],
'202001': [1000, 999, 1983],
'202002': [1001, 1000, 1984],
'202003': [1002, 1001, 1985],
'202004': [1003, 1002, 1986],
'202005': [1004, 1003, 1987],
'202006': [1005, 1003, 1988],
'202007': [3006, 1005, 1989],
'202008': [1007, 1006, 1990],
'202009': [1008, 1007, 1991],
'202010': [1009, 1008, 1992],
'202011': [1010, 1009, 1993],
'202012': [1011, 1010, 1994],
'Date': ['202004', '202006', '202010']
}
df = pd.DataFrame(data)
# 2. 核心计算逻辑
tmp = (df.melt(id_vars=['Code', 'Date'])
.astype({'Date': str, 'variable': str}) # 确保日期字符串可比较
.assign(col=lambda d: np.where(d['Date'].gt(d['variable']), 'Before', 'After')) # 条件判断
.groupby(['Code', 'col'])['value'].sum() # 分组求和
.unstack('col')[['Before', 'After']] # 重构列并确保顺序
)
# 3. 合并回原始DataFrame
out = df.merge(tmp, left_on='Code', right_index=True, how='left')
print(out)运行上述代码,将得到如下输出:
Code 202001 202002 202003 202004 202005 202006 202007 202008 202009 202010 202011 202012 Date Before After 0 12345 1000 1001 1002 1003 1004 1005 3006 1007 1008 1009 1010 1011 202004 3003 11063 1 12346 999 1000 1001 1002 1003 1003 1005 1006 1007 1008 1009 1010 202006 5005 7048 2 12347 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 202010 17883 5979
可以看到,Before和After两列已成功添加到原始DataFrame中,并且数值计算正确。
本教程展示了如何利用Pandas的melt、astype、assign(结合np.where)、groupby、unstack和merge等函数,以声明式和高效的方式解决根据行内特定日期动态聚合数据的问题。这种方法不仅代码简洁,而且在处理中大型数据集时表现良好,是进行复杂数据转换和分析的有力工具。掌握这种数据重塑和聚合的技巧,将极大地提升您在Pandas中的数据处理能力。
以上就是Pandas DataFrame中基于指定日期进行数据聚合与分析的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号