如何按Pandas DataFrame列条件统计零值并优化循环代码
问题描述
在一项识别数据集中正常工作传感器的学校活动中,现有如下Pandas DataFrame:
# Import library import pandas as pd import numpy as np # Define dataframe df = pd.DataFrame({'ID': ['21F', '21F', '21F', '21F', '2H', '2H', '2H', '2H', 'H5', 'H5', 'H5', 'H5'], 'Value': [0, 0, 0, 255, 255, 255, 0, 0, 255, 255, 255, 0], 'Column_n': [0,1,2,3,4,5,6,7,8,9,10,11]}) print(df)
输出的DataFrame内容:
ID Value Column_n 0 21F 0 0 1 21F 0 1 2 21F 0 2 3 21F 255 3 4 2H 255 4 5 2H 255 5 6 2H 0 6 7 2H 0 7 8 H5 255 8 9 H5 255 9 10 H5 255 10 11 H5 0 11
规则说明
- Value=0 表示传感器有效,Value=255 表示传感器无效
- 判断规则:若某ID对应的Value=0的数量≥2,则该传感器有效
当前实现代码
目前通过for循环实现有效/无效传感器ID的分类,但运行耗时较长:
# Create an array ID unique array_id_unique = np.array(df['ID'].unique()) list_id_VALID = [] list_id_INVALID = [] for i in range(0, len(array_id_unique)): id_curr = array_id_unique[i] df_curr = df[df['ID'] == id_curr] if(len(df_curr[df_curr['Value'] == 0]) >= 2): list_id_VALID.append(id_curr) else: list_id_INVALID.append(id_curr)
预期输出
print(list_id_VALID) > ['21F', '2H'] print(list_id_INVALID) > ['H5']
提问:是否有替代for循环的更高效实现方式?
优化方案
用Pandas原生的分组聚合操作替代循环,这是处理这类分组统计场景的最优方式,既能避免循环中反复切片DataFrame的性能损耗,代码也更简洁。
代码实现
# 统计每个ID对应的有效(Value=0)记录数量 valid_counts = df[df['Value'] == 0].groupby('ID').size() # 按规则划分有效/无效ID列表 list_id_VALID = valid_counts[valid_counts >= 2].index.tolist() list_id_INVALID = valid_counts[valid_counts < 2].index.tolist() # 处理无任何有效记录的ID(这类ID默认归为无效) all_unique_ids = df['ID'].unique() list_id_INVALID.extend([id for id in all_unique_ids if id not in valid_counts.index])
代码解释
- 统计有效次数:先筛选出
Value=0的行,再按ID分组统计每组行数,得到每个ID的有效记录数 - 筛选分类:通过布尔索引直接筛选出符合条件的ID,转为列表即可
- 补全无效ID:如果某个ID没有任何有效记录,它不会出现在
valid_counts中,需要把这类ID也加入无效列表,确保结果覆盖所有ID
运行后输出完全符合预期:
print(list_id_VALID) > ['21F', '2H'] print(list_id_INVALID) > ['H5']
内容的提问来源于stack exchange,提问作者Jane Borges
相关产品推荐
相关产品推荐

