如何创建含唯一值的精简DataFrame并汇总结果?
DataFrame按Item聚合处理结果列的问题解决
需求说明
我有一个DataFrame df,包含ID、Item、cost三列(这三列是唯一关联的,比如Apple对应ID12、cost5),其余是无表头的结果列(列名是3、4)。需要生成新的DataFrame df2,要求以唯一Item为行数,规则如下:
- 某Item对应的结果列中存在至少一个Y,就填Y
- 全为N则填N
- 仅含NaN则保留NaN
预期结果
print(df2) ID Item cost 3 4 0 12 Apple 5 Y Y 1 15 Orange 6 N Y 2 21 Lemon 6 Y NaN 3 51 Grape 6 Y N
报错情况
尝试用以下代码实现时,在计算YCount处报KeyError: False错误:
df2 = df.drop_duplicates(subset=['ID', 'Item'], keep='first') #copy df to df2 with ID, Item, cost duplicates removed df2[df2.columns[3:]] = '' #clear column 3 to 4 for i in df2["Item"].unique(): for x in range(3, len(df2.columns)): YCount =(df["Item" == i].df.iloc[:,x] == 'Y').sum() #count number of Y corresponding to the item NCount =(df["Item" == i].df.iloc[:,x] == 'N').sum() #count number of N corresponding to the item if YCount > 0: df2.iloc[:,x] = "Y" #if more than zero Y appears, put Y elif YCount + NCount == 0: df2.iloc[:,x] = "" #if total Y and N is 0, put NaN elif YCount == 0 and NCount > 0: df2.iloc[:,x] = "N" #if Y=0 and N more than 0, put N
错误分析
原代码存在三个核心问题:
- 筛选语法错误:
df["Item" == i]是错误的筛选方式,正确写法应为df[df["Item"] == i],且多余的.df调用属于冗余,会导致属性错误 - 赋值范围错误:
df2.iloc[:,x] = "Y"会将整列所有行改为Y,而非当前Item对应的行 - 缺失值处理错误:用空字符串
""代替NaN不符合pandas的缺失值规范,应该使用np.nan
解决方案
方法一:使用groupby聚合(推荐)
这种方式无需循环,更高效简洁,同时保证关联列的唯一性:
import pandas as pd import numpy as np # 定义针对单列的聚合函数 def aggregate_result(series): has_y = (series == 'Y').any() has_n = (series == 'N').any() if has_y: return 'Y' elif has_n: return 'N' else: return np.nan # 按唯一关联列分组,对结果列应用聚合函数 df2 = df.groupby(['ID', 'Item', 'cost'], as_index=False).agg(aggregate_result)
方法二:修正原循环写法
如果坚持使用循环实现,修正后的代码如下:
import pandas as pd import numpy as np # 保留唯一的ID-Item-cost组合,重置索引方便定位 df2 = df.drop_duplicates(subset=['ID', 'Item'], keep='first').reset_index(drop=True) # 初始化结果列为NaN df2[df2.columns[3:]] = np.nan # 遍历每个唯一Item及其对应的行索引 for row_idx, item in enumerate(df2['Item']): # 筛选当前Item的所有原始数据行 item_data = df[df['Item'] == item] # 遍历所有结果列 for col in df2.columns[3:]: y_count = (item_data[col] == 'Y').sum() n_count = (item_data[col] == 'N').sum() if y_count > 0: df2.loc[row_idx, col] = 'Y' elif n_count > 0: df2.loc[row_idx, col] = 'N' # 无Y无N时保留NaN,无需额外操作
内容的提问来源于stack exchange,提问作者Kenny
相关产品推荐
相关产品推荐

