Python Pandas按时间区间统计DataFrame单元格数量的实现及报错解决
Python Pandas按时间区间统计DataFrame单元格数量的实现及报错解决
先来说说你最初代码里的问题哈,你遇到的*TypeError: 'numpy.ndarray' object is not callable*主要有几个原因:
- key的理解错误:你在
for key, value in data_df.items()里,key是DataFrame的列名,不是单元格里的数值,所以if key <= 300这个判断完全不对,列名一般是字符串或者整数索引,但这里显然不是你要判断的数值范围。 - count()方法的误用:
value.count(value.values() <= 300)这种写法是错的,count()用来统计非缺失值的数量,不能这么传条件。要统计满足条件的单元格数量,应该用布尔索引后求和——因为布尔值True会被当作1,False当作0,求和就是符合条件的数量。
那你最初统计小于300秒的需求,其实不用循环,一行代码就能搞定:
# 先处理缺失值,然后统计小于300的数量 df_count_less_300 = data_df.fillna(0).astype(int).lt(300).sum().iloc[0] print(df_count_less_300)
解释一下:
fillna(0)把空值换成0astype(int)转成整数类型lt(300)生成布尔值的DataFrame,满足条件的是Truesum()对每列求和(这里你只有一列,所以取第一列的结果)
然后来看你更新后的需求:按5分钟间隔(300秒)统计到1小时(3600秒)的各个区间的数量,这里有两种简单的方法:
方法一:用布尔条件逐个统计
适合你需要明确每个区间的统计结果:
# 先预处理数据,填充空值转整数 processed_df = data_df.fillna(0).astype(int) # 定义区间对应的条件和名称 intervals = [ ("0-5分钟(0-300秒)", processed_df[0].between(0, 300, inclusive='left')), ("5-10分钟(300-600秒)", processed_df[0].between(300, 600, inclusive='left')), ("10-15分钟(600-900秒)", processed_df[0].between(600, 900, inclusive='left')), ("15-20分钟(900-1200秒)", processed_df[0].between(900, 1200, inclusive='left')), ("20-25分钟(1200-1500秒)", processed_df[0].between(1200, 1500, inclusive='left')), ("25-30分钟(1500-1800秒)", processed_df[0].between(1500, 1800, inclusive='left')), ("30-35分钟(1800-2100秒)", processed_df[0].between(1800, 2100, inclusive='left')), ("35-40分钟(2100-2400秒)", processed_df[0].between(2100, 2400, inclusive='left')), ("40-45分钟(2400-2700秒)", processed_df[0].between(2400, 2700, inclusive='left')), ("45-50分钟(2700-3000秒)", processed_df[0].between(2700, 3000, inclusive='left')), ("50-55分钟(3000-3300秒)", processed_df[0].between(3000, 3300, inclusive='left')), ("55-60分钟(3300-3600秒)", processed_df[0].between(3300, 3600, inclusive='left')), ] # 遍历统计并打印结果 for name, condition in intervals: count = condition.sum() print(f"{name}: {count} 个")
这里用between(left, right, inclusive='left')表示左闭右开区间,避免重复统计边界值(比如300秒只会算在5-10分钟的区间里)。
方法二:用pd.cut批量分组统计
如果想更高效地生成所有区间的统计结果,推荐用pd.cut:
# 预处理数据 processed_series = data_df[0].fillna(0).astype(int) # 定义区间边界:从0到3600,步长300 bins = list(range(0, 3601, 300)) # 定义每个区间的标签 labels = [f"{i//60}-{(i+300)//60}分钟" for i in bins[:-1]] # 分组统计 counts = pd.cut(processed_series, bins=bins, labels=labels, include_lowest=True).value_counts() # 打印结果 print(counts)
解释一下:
bins生成[0,300,600,...,3600]的区间边界labels自动生成对应的分钟区间标签include_lowest=True确保0秒的数值被包含在第一个区间里value_counts()直接统计每个区间的数量,结果是一个Series,清晰展示每个区间的统计数
最后,你之前写的df_count300to600 = data_df[key].fillna(0).le( key > 300 && key < 600)有两个问题:一是Python里逻辑与要用and,但在Pandas布尔索引里要换成&;二是le()是小于等于的方法,你这里的条件逻辑完全错了,正确的写法应该是(data_df[key] > 300) & (data_df[key] < 600),然后求和得到数量。
备注:内容来源于stack exchange,提问作者Felipe Abrão Mariotti
相关产品推荐
相关产品推荐

