Pandas DataFrame中如何统计日期列表类型列满足条件的行数
Pandas列表类型列过滤与元素访问问题
问题描述
现有一个Pandas DataFrame,其中Views列的值为日期列表。需要统计该DF中符合要求的非空行数,即排除Views值等于[1970-01-01 00:00:00](类型为datetime列表)的行。
初始尝试的错误写法
a = datetime.strptime('1970-01-01 00:00:00', '%Y-%m-%d %H:%M:%S') result.loc[result.Views[0] != a ] result.loc[result.Views[0][0] != a ] result.loc[result.Views[0][0] != [a] ] result.loc[result.Views[0] != [a] ]
上述写法以及isin、unique等函数的尝试,运行后要么报KeyValue错误,要么报list not hashable错误。
已验证的可行方案
初始可行版本
a = datetime.strptime('1970-01-01 00:00:00', '%Y-%m-%d %H:%M:%S') test = result.explode('Views') out = test[test.Views != a] result['Count'] = result.Views.apply(lambda x: sum(y != a for y in x)) viewed = len(result.loc[result.Count > 0]) # 统计有有效浏览记录的总行数
该方案可正常运行,但存在优化空间,同时遗留两个待解决问题:
- 有没有更简单高效的实现方式?
- 如果DataFrame中的值是列表,要如何通过索引访问列表内的元素?
优化后的最简版本
print(len(df.loc[df["Views"].apply(lambda l: pd.Series(l).explode().ne("1970-01-01").all())]))
最优解决方案
1. 高效统计符合要求的行数
无需生成中间表或额外列,直接通过apply做列表匹配即可,性能优于多层explode的写法:
import pandas as pd from datetime import datetime target_time = datetime(1970, 1, 1, 0, 0, 0) # 过滤条件:Views列表不等于[target_time],且非空 valid_mask = df["Views"].apply(lambda x: x != [] and x != [target_time]) # 统计符合条件的行数 valid_row_count = valid_mask.sum()
如果需要过滤所有全部元素都是1970-01-01的列表(无论列表长度),可以调整过滤条件:
valid_mask = df["Views"].apply(lambda x: any(item != target_time for item in x))
2. 列表类型列按索引访问元素
直接在apply中访问对应索引即可,建议增加长度判断避免索引越界报错:
# 取每个Views列表的第一个元素,列表为空时返回空值 df["first_view_date"] = df["Views"].apply(lambda x: x[0] if len(x) > 0 else pd.NA) # 取每个Views列表的第三个元素,列表长度不足3时返回空值 df["third_view_date"] = df["Views"].apply(lambda x: x[2] if len(x) > 2 else pd.NA)
内容的提问来源于stack exchange,提问作者Laurel
相关产品推荐
相关产品推荐

