如何在C#中用Deedle筛选不可按日期索引的训练日志数据
使用Deedle筛选CSV中指定日期后的训练日志数据
问题场景
CSV格式的训练日志中,Date列存在重复值,无法直接将其设为索引,需要筛选出2022年8月15日及之后的训练记录,使用Deedle库时遇到Rows.After需要复合索引的问题。
解决方案
无需对数据进行分组,直接针对原始Frame的Date列做过滤是更简洁高效的方式:
修改后的完整代码
using Deedle; using System; using System.IO; namespace Volume_Analysis_Tool { public class Program { static void Main(string[] args) { // 读取CSV文件,自动推断列类型 Frame<int, string> workouts = Frame.ReadCsv( Path.Combine(Environment.CurrentDirectory, "./data/strong218049301181757984.csv"), hasHeaders: true, separators: ";", inferTypes: true); // 筛选2022年8月15日及之后的行 var filteredWorkouts = workouts.Rows.Where(row => row.GetAs<DateTime>("Date") >= new DateTime(2022, 8, 15)); // 打印筛选结果 filteredWorkouts.Print(); } } }
关键说明
- 移除无用引用:删除了代码中未用到的
System.Net.Sockets、System.Runtime.CompilerServices等命名空间,精简代码结构。 - 直接过滤行:通过
Rows.Where方法遍历每一行,判断Date列的值是否大于等于目标日期,直接得到符合条件的数据集,避免了分组带来的复合索引问题。 - 类型安全处理:使用
GetAs<DateTime>("Date")确保Date列以DateTime类型读取,由于初始化时设置了inferTypes: true,Deedle已自动推断出该列的类型。
若坚持使用分组后的处理(不推荐)
如果一定要基于分组后的Frame操作,需要传入分组后的复合索引键(日期+组内序号),示例如下:
var grouped = workouts.GroupRowsBy<DateTime>("Date"); // 筛选分组后日期在2022-08-15之后的所有组 var filteredGrouped = grouped.Rows.After(new Tuple<DateTime, int>(new DateTime(2022, 8, 15), int.MinValue)); // 将分组数据展开为原始行结构 var filteredWorkouts = filteredGrouped.SelectMany(group => group.Value.Rows); filteredWorkouts.Print();
这种方式需要额外展开分组,效率低于直接过滤原始数据,仅在有其他分组需求时使用。
内容的提问来源于stack exchange,提问作者Vocaloidas
相关产品推荐
相关产品推荐

