第7章 时间维度的雕琢:日期时间数据的清洗与计算艺术
第7章 时间维度的雕琢日期时间数据的清洗与计算艺术在数据分析的世界里时间维度是最常见的分析轴线之一。无论是销售趋势分析、用户行为轨迹追踪还是项目进度监控日期时间数据都扮演着核心角色。然而原始的日期时间数据往往并不友善它们可能是字符串、可能是数字、可能包含时区信息、可能格式不统一。更常见的是我们需要从时间点中提取特定的成分如年份、月份、星期几或者计算两个时间点之间的间隔或者基于已知时间推算未来的某个时间点。本章将深入探讨如何利用ChatGPT与pandas的强大日期时间处理能力对时间点数据和时间段数据进行系统化的整理与计算。我们将从基础概念讲起逐步深入到实际商业场景中的应用每个知识点都配有可直接运行的代码实例。通过本章的学习你将能够游刃有余地处理各种日期时间相关的分析需求。7.1 时间点数据的精炼从原始时间中提取业务特征时间点数据是指具体的时刻如“2024年3月21日14时30分”。在业务分析中我们常常需要从这个时间点中提取出具体的成分比如“2024”年、“3”月、“21”日或者判断它是星期几、是否周末、属于哪个季度等。这些提取出来的成分可以作为新的特征用于分组聚合、趋势分析或模型输入。从技术原理上讲pandas将日期时间数据存储为datetime64类型这是一种高效的整数数组底层以纳秒为单位存储。通过dt访问器我们可以轻松地访问各种时间成分如.dt.year、.dt.month、.dt.dayofweek等。这些操作都是向量化的能够以极快的速度处理数百万条记录。7.1.1 时间成分的拆解从日期时间中提取单位数字在商业分析中按年、月、日、时、分等维度进行分组统计是最常见的需求。例如分析每年、每月的销售额变化趋势或者按小时分析用户活跃度。要实现这些分析首先需要从完整的时间戳中提取出对应的单位。商业实例某在线教育平台拥有一份“用户学习记录表”其中“学习开始时间”列记录了每次学习的起始时刻。运营团队希望统计各个月份的学习总时长以便了解用户的学习习惯随月份的变化。我们需要从“学习开始时间”中提取出月份然后进行分组聚合。importpandasaspdclassDateTimeComponentExtractor: 日期时间成分提取器从datetime列中提取年、月、日、时、分等 def__init__(self,Data):self.DataDatadefEnsureDatetime(self,ColumnName): 确保列为datetime类型 ifnotpd.api.types.is_datetime64_any_dtype(self.Data[ColumnName]):self.Data[ColumnName]pd.to_datetime(self.Data[ColumnName])print(f已将列{ColumnName}转换为datetime类型)returnself.DatadefExtractYear(self,ColumnName,NewColName年份): 提取年份 self.EnsureDatetime(ColumnName)self.Data[NewColName]self.Data[ColumnName].dt.yearprint(f已从{ColumnName}提取年份到{NewColName})returnself.DatadefExtractMonth(self,ColumnName,NewColName月份): 提取月份 self.EnsureDatetime(ColumnName)self.Data[NewColName]self.Data[ColumnName].dt.monthprint(f已从{ColumnName}提取月份到{NewColName})returnself.DatadefExtractDay(self,ColumnName,NewColName日期): 提取日月份中的第几天 self.EnsureDatetime(ColumnName)self.Data[NewColName]self.Data[ColumnName].dt.dayprint(f已从{ColumnName}提取日期到{NewColName})returnself.DatadefExtractHour(self,ColumnName,NewColName小时): 提取小时 self.EnsureDatetime(ColumnName)self.Data[NewColName]self.Data[ColumnName].dt.hourprint(f已从{ColumnName}提取小时到{NewColName})returnself.DatadefExtractMinute(self,ColumnName,NewColName分钟): 提取分钟 self.EnsureDatetime(ColumnName)self.Data[NewColName]self.Data[ColumnName].dt.minuteprint(f已从{ColumnName}提取分钟到{NewColName})returnself.DatadefExtractQuarter(self,ColumnName,NewColName季度): 提取季度 self.EnsureDatetime(ColumnName)self.Data[NewColName]self.Data[ColumnName].dt.quarterprint(f已从{ColumnName}提取季度到{NewColName})returnself.Data# 商业实例提取月份用于分析学习时长if__name____main__:# 模拟用户学习记录studyData{用户ID:[1001,1002,1003,1001,1002],学习开始时间:[2024-01-15 09:30:00,2024-02-20 14:15:00,2024-02-25 19:00:00,2024-03-10 08:45:00,2024-03-18 21:30:00],学习时长(分钟):[45,60,30,90,120]}dfStudypd.DataFrame(studyData)extractorDateTimeComponentExtractor(dfStudy)extractor.ExtractMonth(学习开始时间,月份)# 按月份统计学习总时长monthlyStatsdfStudy.groupby(月份)[学习时长(分钟)].sum().reset_index()print(\n各月份学习总时长:)print(monthlyStats)在这个实例中我们通过dt.month轻松提取了月份并用于分组聚合。EnsureDatetime方法确保了列是datetime类型这在处理从Excel或CSV导入的数据时尤为重要因为那些数据通常以字符串形式存在。如果原始数据包含多种日期格式pd.to_datetime会自动尝试解析但速度较慢ChatGPT可以帮助我们编写自定义解析函数或者指定format参数来提高效率。7.1.2 星期几的判断挖掘周期性规律“星期几”是另一个极其重要的时间特征。零售业的销售数据通常呈现“周末效应”餐饮行业的订单量可能在周五达到高峰在线教育的用户活跃度可能在周末下降。通过判断日期是星期几我们可以将这些周期性规律纳入分析。pandas提供了dt.dayofweek返回0-6周一为0和dt.day_name()返回星期名称两种方式。为了方便业务人员理解通常将数字映射为中文或英文名称。商业实例某咖啡连锁店希望了解一周中哪一天的销售额最高以便调整员工排班和促销活动。我们有一份“订单表”包含“订单日期”列需要提取“星期几”并进行统计。importpandasaspdclassWeekdayExtractor: 星期几提取器 def__init__(self,Data):self.DataDatadefEnsureDatetime(self,ColumnName):ifnotpd.api.types.is_datetime64_any_dtype(self.Data[ColumnName]):self.Data[ColumnName]pd.to_datetime(self.Data[ColumnName])returnself.DatadefAddWeekdayNumber(self,DateCol,NewColName星期几(数字)): 添加星期几的数字表示周一0周日6 self.EnsureDatetime(DateCol)self.Data[NewColName]self.Data[DateCol].dt.dayofweekprint(f已从{DateCol}提取星期几数字到{NewColName})returnself.DatadefAddWeekdayName(self,DateCol,NewColName星期几,Localezh): 添加星期几的名称 Locale: zh 中文en 英文 self.EnsureDatetime(DateCol)ifLocalezh:# 手动映射为中文dayMapping{0:周一,1:周二,2:周三,3:周四,4:周五,5:周六,6:周日}self.Data[NewColName]self.Data[DateCol].dt.dayofweek.map(dayMapping)else:self.Data[NewColName]self.Data[DateCol].dt.day_name()print(f已从{DateCol}提取星期几名称到{NewColName})returnself.DatadefIsWeekend(self,DateCol,NewColName是否周末): 判断是否为周末周六或周日 self.EnsureDatetime(DateCol)self.Data[NewColName]self.Data[DateCol].dt.dayofweek5print(f已从{DateCol}判断是否周末到{NewColName})returnself.Data# 商业实例分析一周中各天的销售额if__name____main__:orderData{订单号:[ORD001,ORD002,ORD003,ORD004,ORD005,ORD006,ORD007],订单日期:[2024-03-18,2024-03-19,2024-03-20,2024-03-21,2024-03-22,2024-03-23,2024-03-24],销售额:[1250,980,1120,1350,2100,2450,1980]}dfOrderspd.DataFrame(orderData)extractorWeekdayExtractor(dfOrders)extractor.AddWeekdayName(订单日期,星期几,Localezh)extractor.IsWeekend(订单日期,是否周末)# 按星期几统计平均销售额weekdayStatsdfOrders.groupby(星期几)[销售额].mean().reset_index()# 调整顺序weekdayOrder[周一,周二,周三,周四,周五,周六,周日]weekdayStats[星期几]pd.Categorical(weekdayStats[星期几],categoriesweekdayOrder,orderedTrue)weekdayStatsweekdayStats.sort_values(星期几)print(\n各星期平均销售额:)print(weekdayStats)# 周末与非周末对比weekendStatsdfOrders.groupby(是否周末)[销售额].mean()print(\n周末与非周末平均销售额:)print(weekendStats)通过添加“星期几”和“是否周末”列我们不仅能够看到周一至周日的变化趋势还能直接对比周末和工作日的差异。这种特征在后续的预测模型中也非常有用。ChatGPT可以帮助我们将数字星期转换为任意语言或自定义的星期名称只需提供映射关系即可。7.2 时间段数据的推演从时间点到时间跨度时间段数据关注的是两个时间点之间的跨度或者从一个时间点出发经过一段间隔后的新时间点。这类操作在合同管理、项目计划、账龄分析、生命周期分析等场景中极为常见。例如计算订单从下单到发货的天数或者根据合同起始日和有效期计算截止日。pandas中两个datetime64类型的列相减会得到一个Timedelta对象它可以转换为天数、秒数等。同时我们可以使用pd.DateOffset或pd.Timedelta来对日期进行加减运算实现日期的偏移。7.2.1 时间间隔的计算从两个时间点得出跨度计算两个日期之间的间隔天数、月数或年数是时间段分析的基础。最常见的例子是计算用户从注册到首次购买的天数、订单从生成到完成的天数、员工在职天数等。pandas中直接相减即可得到Timedelta然后通过.dt.days获取天数。商业实例某电商公司希望分析订单的处理效率即从“下单时间”到“发货时间”的平均间隔天数。如果间隔过长可能意味着仓库处理能力不足或存在其他问题。我们需要计算每笔订单的“处理天数”然后进行统计。importpandasaspdclassTimeDeltaCalculator: 时间间隔计算器 def__init__(self,Data):self.DataDatadefEnsureDatetime(self,ColumnName):ifnotpd.api.types.is_datetime64_any_dtype(self.Data[ColumnName]):self.Data[ColumnName]pd.to_datetime(self.Data[ColumnName])returnself.DatadefDaysBetween(self,StartCol,EndCol,NewColName间隔天数): 计算两个日期之间的天数差结束-开始 self.EnsureDatetime(StartCol)self.EnsureDatetime(EndCol)self.Data[NewColName](self.Data[EndCol]-self.Data[StartCol]).dt.daysprint(f已计算{StartCol}到{EndCol}的间隔天数保存为{NewColName})returnself.DatadefHoursBetween(self,StartCol,EndCol,NewColName间隔小时): 计算两个日期之间的小时差 self.EnsureDatetime(StartCol)self.EnsureDatetime(EndCol)self.Data[NewColName](self.Data[EndCol]-self.Data[StartCol]).dt.total_seconds()/3600print(f已计算{StartCol}到{EndCol}的间隔小时保存为{NewColName})returnself.DatadefMonthsBetween(self,StartCol,EndCol,NewColName间隔月数): 近似计算两个日期之间的月数差使用年份差*12 月份差不考虑日 self.EnsureDatetime(StartCol)self.EnsureDatetime(EndCol)# 近似计算如果需要精确可以处理日期的差异self.Data[NewColName](self.Data[EndCol].dt.year-self.Data[StartCol].dt.year)*12\(self.Data[EndCol].dt.month-self.Data[StartCol].dt.month)print(f已计算{StartCol}到{EndCol}的近似月数保存为{NewColName})returnself.Data# 商业实例计算订单处理天数if__name____main__:orderData{订单号:[ORD001,ORD002,ORD003,ORD004],下单时间:[2024-03-01 10:15:00,2024-03-02 14:30:00,2024-03-03 09:00:00,2024-03-04 20:45:00],发货时间:[2024-03-02 08:20:00,2024-03-05 11:00:00,2024-03-03 15:30:00,2024-03-06 09:15:00]}dfOrderspd.DataFrame(orderData)calculatorTimeDeltaCalculator(dfOrders)calculator.DaysBetween(下单时间,发货时间,处理天数)calculator.HoursBetween(下单时间,发货时间,处理小时)print(\n订单处理时长:)print(dfOrders[[订单号,处理天数,处理小时]])avgDaysdfOrders[处理天数].mean()avgHoursdfOrders[处理小时].mean()print(f\n平均处理天数:{avgDays:.1f}天)print(f平均处理小时:{avgHours:.1f}小时)在这个例子中我们计算了天数和小时数。注意直接使用.dt.days只返回整数天数而.dt.total_seconds()返回总秒数除以3600得到小时数。对于订单处理效率分析小时级精度可能更有价值尤其是当天发货的订单。ChatGPT可以帮助我们实现更复杂的间隔计算比如只计算工作日天数、精确到分钟的间隔等。7.2.2 日期的推算已知起点和间隔求终点与计算间隔相反有时我们已知起始日期和一段间隔如3个月、10天需要推算结束日期。这在合同到期日计算、还款计划生成、项目排期等场景中非常常见。pandas中我们可以使用pd.DateOffset或pd.Timedelta来对日期列进行加法运算。DateOffset支持年、月、日、工作日等复杂偏移而Timedelta只支持固定时间单位天、小时等。商业实例某人力资源系统需要为每位新员工自动计算转正日期入职后3个月。同时对于试用期员工如果入职日期是月底转正日期应设定为相应月份的月底。我们可以使用DateOffset(months3)来实现。importpandasaspdclassDateOffsetCalculator: 日期偏移计算器根据起始日期和间隔计算目标日期 def__init__(self,Data):self.DataDatadefEnsureDatetime(self,ColumnName):ifnotpd.api.types.is_datetime64_any_dtype(self.Data[ColumnName]):self.Data[ColumnName]pd.to_datetime(self.Data[ColumnName])returnself.DatadefAddDays(self,StartCol,Days,NewColName): 增加指定天数 self.EnsureDatetime(StartCol)self.Data[NewColName]self.Data[StartCol]pd.Timedelta(daysDays)print(f已为{StartCol}增加{Days}天保存为{NewColName})returnself.DatadefAddMonths(self,StartCol,Months,NewColName,EndOfMonthFalse): 增加指定月数 EndOfMonth: 如果起始日期是月底是否保持月底特性 self.EnsureDatetime(StartCol)# 使用 DateOffset默认会保持日期不变如果超出月份则调整到当月最后一天self.Data[NewColName]self.Data[StartCol]pd.DateOffset(monthsMonths)ifEndOfMonth:# 对于原始日期是月底的情况结果也应为月底isEndOfMonthself.Data[StartCol].dt.is_month_end self.Data.loc[isEndOfMonth,NewColName]self.Data.loc[isEndOfMonth,NewColName]pd.offsets.MonthEnd(0)print(f已为{StartCol}增加{Months}个月保存为{NewColName})returnself.DatadefAddBusinessDays(self,StartCol,BusinessDays,NewColName): 增加指定工作日天数跳过周末 self.EnsureDatetime(StartCol)self.Data[NewColName]self.Data[StartCol]pd.offsets.BDay(BusinessDays)print(f已为{StartCol}增加{BusinessDays}个工作日保存为{NewColName})returnself.Data# 商业实例计算员工转正日期if__name____main__:employeeData{员工ID:[101,102,103,104],姓名:[张三,李四,王五,赵六],入职日期:[2024-01-15,2024-02-28,2024-03-01,2024-03-31]}dfEmployeespd.DataFrame(employeeData)calculatorDateOffsetCalculator(dfEmployees)# 试用期3个月月底入职的员工转正日期也应为月底calculator.AddMonths(入职日期,3,转正日期,EndOfMonthTrue)print(\n员工转正日期:)print(dfEmployees)# 同时计算合同到期日假设合同期为1年calculator.AddMonths(入职日期,12,合同到期日,EndOfMonthFalse)print(\n合同到期日:)print(dfEmployees)在这个实例中我们使用了pd.DateOffset(monthsMonths)来增加月份并通过is_month_end判断是否为月底从而正确处理月底入职的情况。pd.offsets.BDay可以用于计算工作日这在项目排期、任务截止日计算中非常实用。ChatGPT可以帮助我们选择正确的偏移类型并处理各种边界情况比如闰年、月末等。通过本章的学习我们系统地掌握了日期时间数据的核心处理方法。从时间点成分的提取到星期几的判断再到时间间隔的计算和日期的推算每一个技能都能直接应用于实际的商业分析中。无论是用户行为分析、运营效率评估还是财务预测、项目管理日期时间处理都是不可或缺的基础。在下一章中我们将继续探索数据分析的更高阶主题——数据可视化让枯燥的数字通过图表讲述生动的故事。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2438415.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!