如何在Pandas中基于DateTime按ID生成月度犯罪类型计数列
问题描述
现有一个存储犯罪事件的大型DataFrame df,包含四列,其中INCIDENT_DATE为datetime类型,犯罪类型分为Violent(暴力犯罪)、Property(财产犯罪)和非索引类。示例数据如下:
| ID | 犯罪事件 | 事件日期 | 类型 |
|---|---|---|---|
| XL123445 | 严重袭击 | 2018-12-29 | Violent |
| XL123445 | 轻微袭击 | 2018-12-29 | Violent |
| XL123445 | 盗窃 | 2018-12-30 | Property |
| TX56784 | 盗窃 | 2018-04-28 | Property |
| ... | ... | ... | ... |
| CA45678 | 性袭击 | 1991-10-23 | Violent |
| LA356890 | 入室盗窃 | 2018-12-21 | Property |
需要生成一个新的DataFrame,按每个ID和月份统计暴力犯罪、财产犯罪的数量,以及该ID当月的事件总数,目标格式如下:
| ID | 年月 | 暴力犯罪 | 财产犯罪 | 总计 |
|---|---|---|---|---|
| XL123445 | 2018-08 | 19654 | 500 | 20154 |
| TX56784 | 2011-07 | 17 | 15 | 32 |
| ... | ... | ... | ... | ... |
| CA45678 | 1992-06 | 100 | 100 | 200 |
| LA356890 | 1993-05 | 0 | 50 | 50 |
注:目标表格中LA356890行的“暴力犯罪”列原内容有误,已修正为0。
此前已通过以下代码生成按ID和Year_Month统计总事件数的DataFrame,但未区分犯罪类型:
df1 = (df.value_counts(['ID', df['INCIDENT_DATE'].dt.to_period('M').rename('Year_Month')]) .rename('Count').reset_index())
请问如何沿用该逻辑生成所需的额外列?
解决方案
方法一:基于value_counts的链式写法(沿用原有逻辑)
在原有value_counts的基础上,加入犯罪类型作为统计维度,再通过透视表将类型转为列,最后计算总计:
result = (df # 提取年月列,统一命名为Year_Month .assign(Year_Month=df['INCIDENT_DATE'].dt.to_period('M')) # 按ID、年月、类型统计事件数,对应带维度的value_counts .value_counts(['ID', 'Year_Month', '类型']) .rename('Count') .reset_index() # 透视表将类型转为列,缺失值填充为0(代表当月无该类型犯罪) .pivot(index=['ID', 'Year_Month'], columns='类型', values='Count') .fillna(0) .astype(int) # 只保留需要的暴力和财产犯罪列,并重命名为中文 .filter(['Violent', 'Property']) .rename(columns={'Violent': '暴力犯罪', 'Property': '财产犯罪'}) # 计算当月事件总计 .assign(总计=lambda x: x['暴力犯罪'] + x['财产犯罪']) # 重置索引,转为目标格式的平级列 .reset_index())
方法二:groupby聚合(更高效的替代方案)
如果处理超大型数据集,groupby聚合的性能会更优,逻辑也更直接:
result = (df .assign(Year_Month=df['INCIDENT_DATE'].dt.to_period('M')) # 按ID和年月分组,对类型列做聚合统计 .groupby(['ID', 'Year_Month'])['类型'] .agg( 暴力犯罪=lambda x: (x == 'Violent').sum(), 财产犯罪=lambda x: (x == 'Property').sum() ) # 计算总计 .assign(总计=lambda x: x['暴力犯罪'] + x['财产犯罪']) .reset_index())
两种方法最终都会生成符合要求的DataFrame,其中方法一完全沿用了你最初使用value_counts的统计思路,方法二则更适合大规模数据的快速处理。
内容的提问来源于stack exchange,提问作者TheMaffGuy
相关产品推荐
相关产品推荐

