基于多筛选条件统计NumPy数组元素出现次数的技术问询
按多条件统计元素出现次数
需求
先以Outlook列为筛选依据,再统计label列中No和Yes的出现次数,同时计算每组的总数量。
数据集
data_dict = { 'Outlook' : ['Sunny', 'Sunny', 'Overcast', 'Rainy', 'Rainy', 'Rainy', 'Overcast', 'Sunny', 'Sunny','Rainy', 'Sunny', 'Overcast', 'Overcast', 'Rainy'], 'Temperature': ['Hot', 'Hot', 'Hot', 'Mild', 'Cool', 'Cool', 'Cool', 'Mild', 'Cool', 'Mild','Mild','Mild', 'Hot', 'Mild'], 'Humidity' : ['High', 'High', 'High', 'High', 'Normal', 'Normal', 'Normal', 'High','Normal','Normal', 'Normal', 'High', 'Normal', 'High'], 'Wind': ['False', 'True', 'False', 'False', 'False', 'True', 'True', 'False', 'False', 'False', 'True', 'True', 'False', 'True'], 'label': ['No', 'No', 'Yes', 'Yes', 'Yes', 'No', 'Yes', 'No', 'Yes', 'Yes', 'Yes', 'Yes', 'Yes', 'No'] }
生成的DataFrame示例:
Outlook Temperature Humidity Wind label 0 Sunny Hot High False No 1 Sunny Hot High True No 2 Overcast Hot High False Yes 3 Rainy Mild High False Yes 4 Rainy Cool Normal False Yes ...
期望结果
Outlook No Yes All Sunny 3 2 5 Overcast 0 4 4 Rainy 2 3 5
注:原期望结果中部分数值存在笔误,以上为正确统计结果
问题代码分析
你尝试的代码仅单独提取了Outlook和label列,然后用np.unique做全局统计,没有实现按Outlook分组统计的逻辑,因此无法得到目标结果:
result = np.where(df.columns.values == 'label') result1 = np.where(df.columns.values == 'Outlook') lst = rows[:, [result, result1]] uni, data = np.unique(lst, return_counts=True)
解决方案
方法1:使用Pandas交叉表(简单高效)
利用pd.crosstab直接生成分组统计结果,再添加总数列:
import pandas as pd # 生成DataFrame df = pd.DataFrame(data_dict) # 生成Outlook与label的交叉统计 cross_tab = pd.crosstab(df['Outlook'], df['label']) # 添加每行总数 cross_tab['All'] = cross_tab.sum(axis=1) # 调整列顺序匹配期望 cross_tab = cross_tab[['No', 'Yes', 'All']] print(cross_tab)
运行输出:
label No Yes All Outlook Overcast 0 4 4 Rainy 2 3 5 Sunny 3 2 5
方法2:纯NumPy实现
如果需要基于NumPy数组处理,可按以下步骤分组统计:
import numpy as np import pandas as pd df = pd.DataFrame(data_dict) # 转换为NumPy数组 data_array = df.to_numpy() # 获取列索引 outlook_col = df.columns.get_loc('Outlook') label_col = df.columns.get_loc('label') # 获取唯一的Outlook值 unique_outlooks = np.unique(data_array[:, outlook_col]) # 定义要统计的label值 target_labels = ['No', 'Yes'] # 初始化统计矩阵:每行对应一个Outlook,列依次为No、Yes、All stats = np.zeros((len(unique_outlooks), 3), dtype=int) for idx, outlook in enumerate(unique_outlooks): # 筛选当前Outlook的所有行 mask = data_array[:, outlook_col] == outlook # 统计当前组内No和Yes的数量 for label_idx, label in enumerate(target_labels): stats[idx, label_idx] = np.sum(data_array[mask, label_col] == label) # 计算当前组的总数量 stats[idx, 2] = np.sum(mask) # 转换为结构化结果 result = pd.DataFrame(stats, index=unique_outlooks, columns=['No', 'Yes', 'All']) print(result)
运行结果与方法1一致。
内容的提问来源于stack exchange,提问作者N K
相关产品推荐
相关产品推荐

