2020-03-24打卡——Task2:数据的探索性分析(EDA)

本文介绍如何利用pandas_profiling库进行数据的探索性分析(EDA)。通过生成全面的可视化报告,揭示数据结构、特征间的关联性和分布情况,为特征构建和模型选择提供指导。

2020-03-24打卡——Task2:数据的探索性分析(EDA)

用pandas_profiling生成数据报告:用pandas_profiling生成一个较为全面的可视化和数据报告(较为简单、方便) 最终打开html文件即可:
import pandas_profiling
pfr = pandas_profiling.ProfileReport(Train_data)
pfr.to_file("./example.html")

variables: 100%
29/29 [1:32:29<00:00, 191.38s/it]

correlations [recoded]: 100%
6/6 [01:06<00:00, 11.12s/it]

interactions [continuous]: 100%
529/529 [03:46<00:00, 2.33it/s]

table: 100%
1/1 [00:04<00:00, 4.68s/it]

missing [matrix]: 100%
2/2 [00:04<00:00, 2.14s/it]

warnings [correlations]: 100%
3/3 [00:00<00:00, 26.83it/s]

package: 100%
1/1 [00:00<00:00, 3.27it/s]

build report structure: 100%
1/1 [00:27<00:00, 27.01s/it]

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

打卡——Task2“EDA”探索数据分析经验总结

所给出的EDA步骤为广为普遍的步骤,在实际的不管是工程还是比赛过程中,这只是最开始的一步,也是最基本的一步。

接下来一般要结合模型的效果以及特征工程等来分析数据的实际建模情况,根据自己的一些理解,查阅文献,对实际问题做出判断和深入的理解。

最后不断进行EDA与数据处理和挖掘,来到达更好的数据结构和分布以及较为强势相关的特征

数据探索在机器学习中我们一般称为EDA(Exploratory Data Analysis):

是指对已有的数据(特别是调查或观察得来的原始数据)在尽量少的先验假定下进行探索,通过作图、制表、方程拟合、计算特征量等手段探索数据的结构和规律的一种数据分析方法。

数据探索有利于我们发现数据的一些特性,数据之间的关联性,对于后续的特征构建是很有帮助的。

对于数据的初步分析(直接查看数据,或.sum(), .mean(),.descirbe()等统计函数)可以从:样本数量,训练集数量,是否有时间特征,是否是时许问题,特征所表示的含义(非匿名特征),特征类型(字符类似,int,float,time),特征的缺失情况(注意缺失的在数据中的表现形式,有些是空的有些是”NAN”符号等),特征的均值方差情况。

分析记录某些特征值缺失占比30%以上样本的缺失处理,有助于后续的模型验证和调节,分析特征应该是填充(填充方式是什么,均值填充,0填充,众数填充等),还是舍去,还是先做样本分类用不同的特征模型去预测。

对于异常值做专门的分析,分析特征异常的label是否为异常值(或者偏离均值较远或者事特殊符号),异常值是否应该剔除,还是用正常值填充,是记录异常,还是机器本身异常等。

对于Label做专门的分析,分析标签的分布情况等。

进步分析可以通过对特征作图,特征和label联合做图(统计图,离散图),直观了解特征的分布情况,通过这一步也可以发现数据之中的一些异常值等,通过箱型图分析一些特征值的偏离情况,对于特征和特征联合作图,对于特征和label联合作图,分析其中的一些关联性。

参考文献

https://tianchi.aliyun.com/notebook-ai/detail?spm=5176.12281978.0.0.6802593a7ZAMVe&postId=95457

<think>嗯,用户给了一个JSON格式的打卡数据,需要统计当前连续打卡次数和最多连续打卡次数。首先,我得仔细看看数据结构。数据分为“regular”和“makeup”两个部分,每个部分下面有日期作为键,对应的值里有timestamp字段。用户的需求是计算连续打卡次数,所以需要把所有日期提取出来,然后按时间排序,再判断连续的情况。 首先,我需要将所有的日期从regular和makeup里提取出来。注意到每个日期对应的timestamp可能不是当天的,比如regular里的2025-03-18对应的timestamp是当天的15:10:30,而makeup里的2025-03-16对应的timestamp是2025-03-18的,这时候日期应该以键名为准还是以timestamp的日期为准呢?用户的问题里,键名是日期,而timestamp可能不同。比如,在makeup的2025-03-16,timestamp是2025-03-18的15:09:33,这时候这个打卡记录应该算作3月16日还是3月18日? 仔细看用户的问题,可能需要以键名作为打卡日期,因为补卡的情况可能允许用户补之前的日期。比如,用户可能在3月18日补打卡3月16日的记录,所以键名是实际打卡的日期,而timestamp是实际提交的时间。因此,处理的时候应该用键名的日期来判断连续打卡,而不是timestamp的日期。 所以步骤应该是: 1. 提取所有regular和makeup中的日期键,转换成datetime对象。 2. 将这些日期排序,并去重(假设可能有重复的日期,但实际可能不会,但代码里应该处理)。 3. 按日期排序后,遍历检查连续的日期,计算当前连续打卡和最大连续打卡。 接下来需要考虑当前连续打卡的定义。当前连续打卡应该是指从今天往前推,连续打卡的天数。但用户的数据是未来日期(2025年),这可能是一个测试数据,所以当前日期可能需要根据数据中的最新日期来确定?或者用户可能希望以数据中的最大日期作为“当前”日期? 比如,在数据中,最大的日期是2025-03-24,出现在regular里,所以当前日期是2025-03-24。那么当前连续打卡次数是从这个日期往前数连续打卡的天数。 而最大连续打卡次数是整个日期序列中最长的连续天数。 所以具体步骤: - 提取所有日期,转换为日期对象,排序,去重。 - 找出这些日期中的最大日期作为当前日期。 - 然后从最大日期开始往前检查,有多少天连续的。 - 同时,计算整个序列中的最长连续天数。 Python代码方面,首先需要遍历data中的两个部分,收集所有日期。然后处理这些日期,排序,去重。然后转换为日期列表,并按顺序排列。 然后,对于当前连续打卡,从最后一个日期开始,往前数连续的天数。比如,如果最后几个日期是24号,23号,22号,那么当前连续打卡是3次。但如果中间有断开,比如24号,22号,那么当前连续打卡是1次。 对于最大连续打卡,需要遍历整个排序后的日期列表,找出最长的连续天数。 需要注意的是,日期必须是连续的,比如2025-03-18和2025-03-19是连续的,但如果中间有一天没有打卡,则中断。 现在,如何处理日期转换?例如,字符串如'2025-03-18'转换为datetime.date对象,方便计算。 代码步骤: 1. 提取所有日期: dates = [] for category in data.values(): for date_str in category.keys(): dates.append(date_str) 然后转换为datetime.date对象,排序,去重。去重是因为可能同一个日期在regular和makeup里都有记录,但用户可能只算一次打卡。 sorted_dates = sorted(list({datetime.datetime.strptime(d, "%Y-%m-%d").date() for d in dates})) 然后,计算最大连续次数和当前连续次数。 当前连续次数:从最大的日期开始,向前检查连续的日期。例如,假设最大的日期是date_n,检查date_n-1是否存在于列表中,存在则继续,直到不连续为止。 最大连续次数:遍历整个日期列表,记录每次连续的次数,取最大值。 需要注意的是,处理日期连续的问题,可以将日期转换为ordinal(即自公元1年1月1日以来的天数),然后检查相邻两个日期是否相差1天。 或者,可以将日期按顺序排列后,遍历每个日期,与前一个日期比较是否相差1天,从而统计连续的天数。 例如: sorted_dates = [date1, date2, date3, ...],按升序排列。但为了计算连续,可能需要倒序吗?或者不管顺序如何? 不,应该先按升序排序,然后计算最长连续,或者当前连续需要从最大的日期开始。例如,假设日期是按升序排列的,最大的日期是最后一个元素。当前连续需要检查该日期之前的日期是否是前一天。 例如,假设排序后的日期列表是升序排列,那么最后一个元素是最大的日期。当前连续次数需要从该日期开始,往前找连续的日期。 比如,列表是:2025-03-16, 2025-03-17, ..., 2025-03-24。 当前连续次数需要从24号开始,检查23号是否存在,然后22号是否存在,依此类推,直到断掉为止。但这种方法可能有问题,因为列表中的日期可能有间隔,比如24号存在,23号不存在,但22号存在的话,这时候当前连续次数是1(仅24号)。 另一种方法是,将日期列表转换为一个集合,然后从最大日期开始,逐天减1,检查是否在集合中,直到不在集合中为止。 比如: current_streak = 0 current_date = max_date while current_date in date_set: current_streak +=1 current_date -= datetime.timedelta(days=1) 这样就能正确计算当前连续打卡次数,无论日期在列表中的顺序如何。这种方法更可靠,因为即使日期列表中有跳跃,但连续的日期存在的话,就会计算进去。例如,假设最大日期是24号,如果23号存在,则current_streak增加到2,然后检查22号是否存在,依此类推。 同样,对于最长连续次数,可以遍历所有日期,但需要避免重复计算。通常的做法是将日期排序后,按顺序检查每个日期与前一个是否连续。例如: sorted_dates = sorted(date_set) max_streak = 0 current = 1 for i in range(1, len(sorted_dates)): if (sorted_dates[i] - sorted_dates[i-1]).days == 1: current +=1 else: max_streak = max(max_streak, current) current = 1 max_streak = max(max_streak, current) # 处理最后一组连续的情况 这样可以得到最长连续天数。 现在,把这些思路转化为代码: 首先,处理数据,提取所有日期,去重,转换为date对象,并收集到一个集合中。然后计算当前连续和最长连续。 但需要注意,如果用户的数据中有未来的日期,或者没有打卡记录,该怎么处理? 例如,假设当前日期是数据中的最大日期,即用户最近一次打卡的日期。但可能这个最大日期是过去的,而实际当前日期可能更晚,这时候连续打卡次数可能为0。不过根据用户提供的数据,可能他们希望以数据中的最大日期作为当前日期来计算连续打卡次数。 所以,现在编写代码: import datetime def calculate_streaks(data): # 提取所有日期 dates = [] for category in data.values(): for date_str in category.keys(): dates.append(date_str) # 转换为date对象并去重 date_set = set() for d in dates: date_obj = datetime.datetime.strptime(d, "%Y-%m-%d").date() date_set.add(date_obj) if not date_set: return 0, 0 # 如果没有打卡记录 sorted_dates = sorted(date_set) max_date = sorted_dates[-1] # 计算当前连续打卡次数 current_streak = 0 current = max_date while current in date_set: current_streak +=1 current -= datetime.timedelta(days=1) # 计算最长连续打卡次数 max_streak = 1 current_streak_long = 1 for i in range(1, len(sorted_dates)): if (sorted_dates[i] - sorted_dates[i-1]).days == 1: current_streak_long +=1 else: max_streak = max(max_streak, current_streak_long) current_streak_long = 1 max_streak = max(max_streak, current_streak_long) return current_streak, max_streak 然后测试这个函数是否能正确处理用户的数据。用户提供的例子中的日期: regular中的日期:2025-03-18,2025-03-24 makeup中的日期:2025-03-16, 2025-03-17, 2025-03-21, 2025-03-22, 2025-03-23, 2025-03-14 所有日期转换为date对象后: 2025-03-14, 16, 17, 18, 21, 22, 23, 24 排序后的顺序是:14,16,17,18,21,22,23,24 现在,最长连续打卡次数: 检查连续情况: 14 -> 16:间隔2天,不连续,当前最长初始为1,之后重置为1(从16开始)。 16 ->17:间隔1天,current_streak_long=2 17->18:间隔1天,current=3 18->21:间隔3天,重置,max_streak=3,current重置为1 21->22:+1,current=2 22->23:+1,current=3 23->24:+1,current=4 循环结束后max_streak=max(3,4)=4。所以最长连续是4天(21-24号连续?不,21到24号之间的日期是21、2223、24,共4天连续。是的。所以最长连续是4天? 当前连续打卡次数:最大日期是24号。检查24号是否存在(是的),然后23号存在吗?是的,在makeup里有2025-03-23。然后22号存在?是的,在makeup。21号存在?是的。20号?不存在。所以从24号开始,往前数,2423、2221,共4天。但用户的数据21号之后是24号吗?或者日期序列中21、2223、24是连续的? 是的,21到24是连续的,所以当前连续打卡次数应为4天? 但根据数据中的日期,24号在regular里,而23号在makeup里。所以24号是存在的,23号存在,22存在,21存在。因此,当前连续打卡次数是4次。而最长连续次数是4次吗? 但是原数据中的日期排序是14,16,17,18,21,22,23,24。其中16到18是连续的吗? 16、17、18是连续的,所以连续3天。之后21到24是连续的4天。因此最长连续是4天。当前连续是2423、2221,共4天。 所以函数的返回应该是当前连续4,最长连续4。 那测试代码是否正确。 现在检查代码中的最长连续计算: 在循环中,初始current_streak_long=1,max_streak=1. i=1(日期16-14的差是2天?原排序后的列表是14,16,17,18,21,22,23,24。排序后的顺序是否正确? 哦,这里可能有问题。我之前假设日期是按照升序排列的,但是上面的示例中的日期顺序是否正确? 例如,用户提供的日期: regular中的日期:2025-03-18,2025-03-24 makeup中的日期:2025-03-16, 2025-03-17, 2025-03-21, 2025-03-22, 2025-03-23, 2025-03-14 这些日期转换为date对象后,排序后的顺序应该是: 2025-03-14, 2025-03-16, 2025-03-17, 2025-03-18, 2025-03-21, 2025-03-22, 2025-03-23, 2025-03-24 所以在sorted_dates中是按时间顺序排列的。 在计算最长连续时: i从1开始,到len(sorted_dates)-1=7: i=0:sorted_dates[0]是14,i=1时是16。sorted_dates[1] - sorted_dates[0]的天数是2天,不等于1,所以max_streak保持1,current_streak_long重置为1。 i=2,sorted_dates[2]是17,sorted_dates[1]是16,差1天,current_streak_long=2,max_streak=2. i=3,sorted_dates[3]是18,差1天,current=3,max=3. i=4,sorted_dates[4]是21,sorted_dates[3]是18,差3天,重置current到1,max保持3. i=5,sorted_dates[5]是22,和21差1天,current=2,max仍3. i=6,23和22差1天,current=3,max仍3. i=7,2423差1天,current=4,max变为4. 循环结束后,max_streak是max(3,4)=4. 所以最长连续是4天,正确。 当前连续:max_date是24号,检查2423、2221都存在,所以current_streak是4。然后检查20号不存在,停止。所以当前连续次数4,最长4次。 那代码是正确的。 那用户的问题中给出的数据结果应该是当前连续4次,最多4次。 现在编写完整的Python代码,处理数据,并输出这两个值。 另外,可能需要注意时区问题,但用户的数据中的timestamp可能不影响,因为日期以键名为准。 所以最终的Python代码大致如下: import datetime data = { "regular": { "2025-03-18": { "timestamp": "2025-03-18 15:10:30" }, "2025-03-24": { "timestamp": "2025-03-24 09:46:22" } }, "makeup": { "2025-03-16": { "timestamp": "2025-03-18 15:09:33" }, "2025-03-17": { "timestamp": "2025-03-24 09:46:28" }, "2025-03-21": { "timestamp": "2025-03-24 09:46:29" }, "2025-03-22": { "timestamp": "2025-03-24 09:46:30" }, "2025-03-23": { "timestamp": "2025-03-24 09:46:32" }, "2025-03-14": { "timestamp": "2025-03-24 09:48:22" } } } def get_streaks(data): # 提取所有日期字符串 dates = [] for category in data.values(): dates.extend(category.keys()) # 转换为date对象并去重 date_set = set() for date_str in dates: date_obj = datetime.datetime.strptime(date_str, "%Y-%m-%d").date() date_set.add(date_obj) if not date_set: return 0, 0 # 获取最晚日期 max_date = max(date_set) # 计算当前连续打卡次数 current_streak = 0 current_date = max_date while current_date in date_set: current_streak += 1 current_date -= datetime.timedelta(days=1) # 计算最长连续打卡次数 sorted_dates = sorted(date_set) max_streak = 1 current_length = 1 for i in range(1, len(sorted_dates)): if (sorted_dates[i] - sorted_dates[i-1]).days == 1: current_length += 1 if current_length > max_streak: max_streak = current_length else: current_length = 1 return current_streak, max_streak current, longest = get_streaks(data) print(f"当前连续打卡次数:{current}次") print(f"最多连续打卡次数:{longest}次") 运行这段代码,应该输出当前连续4次,最多4次。 但需要确认是否正确。比如,如果数据中的日期是14、16、17、18、21、2223、24: 当前连续是从24开始,往前检查23、2221都存在,所以current_streak=4。 最长连续是21-24的4天,而16-18是3天,所以最长是4。 所以代码是正确的。</think>分步解决方案及Python代码实现如下: ### 步骤分析 1. **数据提取**:从嵌套字典中提取所有日期字符串 2. **日期处理**:转换为日期对象并去重 3. **排序处理**:获得按时间顺序排列的日期列表 4. **当前连续**:从最新日期开始向前追溯连续打卡天数 5. **最长连续**:遍历所有日期计算最长连续区间 ### Python实现代码 ```python import datetime def calculate_streaks(data): # 提取所有日期键并转换日期对象 date_set = set() for category in data.values(): for date_str in category.keys(): date_obj = datetime.datetime.strptime(date_str, "%Y-%m-%d").date() date_set.add(date_obj) if not date_set: return 0, 0 sorted_dates = sorted(date_set) max_date = sorted_dates[-1] # 计算当前连续打卡 current_streak = 0 check_date = max_date while check_date in date_set: current_streak += 1 check_date -= datetime.timedelta(days=1) # 计算最长连续打卡 max_streak = 1 current_length = 1 for i in range(1, len(sorted_dates)): if (sorted_dates[i] - sorted_dates[i-1]).days == 1: current_length += 1 max_streak = max(max_streak, current_length) else: current_length = 1 return current_streak, max_streak # 测试数据 data = { "regular": { "2025-03-18": { "timestamp": "2025-03-18 15:10:30" }, "2025-03-24": { "timestamp": "2025-03-24 09:46:22" } }, "makeup": { "2025-03-16": { "timestamp": "2025-03-18 15:09:33" }, "2025-03-17": { "timestamp": "2025-03-24 09:46:28" }, "2025-03-21": { "timestamp": "2025-03-24 09:46:29" }, "2025-03-22": { "timestamp": "2025-03-24 09:46:30" }, "2025-03-23": { "timestamp": "2025-03-24 09:46:32" }, "2025-03-14": { "timestamp": "2025-03-24 09:48:22" } } } current, longest = calculate_streaks(data) print(f"当前连续打卡次数:{current}次") # 输出:4次 print(f"最多连续打卡次数:{longest}次") # 输出:4次 ``` ### 关键点说明 1. **日期处理**:使用集合`date_set`自动去重,确保每个日期唯一 2. **当前连续计算**:从最新日期开始逆序检查连续日期 3. **最长连续计算**:通过正向遍历已排序日期列表,动态计算最长连续区间 4. **时间复杂度**:$O(n)$线性复杂度,适合大数据量处理 ### 数学表达 当判断日期连续性时,对于有序日期序列$D = [d_1, d_2,...,d_n]$,连续条件满足: $$d_{i} - d_{i-1} = 1 \quad (\text{天})$$ 通过维护当前连续长度$L$和最大长度$M$,可得: $$M = \max(L_{current}, M_{prev})$$ 此方法保证在$O(n)$时间复杂度内完成计算,效率最优。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值