Pandas DataFrame两类需求:行计数与高价低评分条目标记
嘿,我来帮你搞定这两个Pandas问题!先从你给出的代码问题入手,再处理第一个统计行数的需求~
需求二:标记薪资更高但评分更低的“溢价”玩家
先看你的代码问题:你写的df['Score'].iloc[:]>df['Score'] & df['Salary'].iloc[:]<df['Salary']有几个明显问题:
iloc[:]就是取整个列,拿列和自身比较结果全是False,完全不是你要的“和其他行比较”;- 逻辑运算符
&的优先级比比较运算符高,必须给每个比较表达式单独加括号; count()是统计非空值数量,不是统计满足条件的行数,应该用sum()(因为True会被当作1,False当作0)。
结合你的期望输出,你其实是要对每一行,统计有多少其他玩家薪资比当前行低,但评分比当前行高(这样就能看出当前玩家是不是“薪资高但性价比低”)。下面是修正后的代码:
方法一:用apply(新手友好,逻辑清晰)
import pandas as pd # 构建你的DataFrame df = pd.DataFrame( [['A',12000,100],['B',13000,110],['C',13300,105],['D',12500,102],['E',11800,101]], columns=['Player','Salary','Score'] ) # 定义函数,计算每行的OverPriced数量 def count_overpriced(row): # 筛选出薪资低于当前行、同时评分高于当前行的玩家,统计数量 return ((df['Salary'] < row['Salary']) & (df['Score'] > row['Score'])).sum() # 按行应用函数,生成OverPriced列 df['OverPriced'] = df.apply(count_overpriced, axis=1) print(df)
运行后就能得到你要的结果:
Player Salary Score OverPriced 0 A 12000 100 1 1 B 13000 110 0 2 C 13300 105 1 3 D 12500 102 0 4 E 11800 101 0
方法二:用numpy广播(大数据量更高效)
如果你的数据集很大,apply会比较慢,推荐用广播的方式,直接用矩阵运算:
import pandas as pd df = pd.DataFrame( [['A',12000,100],['B',13000,110],['C',13300,105],['D',12500,102],['E',11800,101]], columns=['Player','Salary','Score'] ) # 把薪资和评分转成numpy数组 salary_vals = df['Salary'].values score_vals = df['Score'].values # 广播生成比较矩阵:每行是当前值和所有值的比较结果 salary_lower = salary_vals[:, None] > salary_vals # 当前行薪资 > 其他行薪资 score_higher = score_vals[:, None] < score_vals # 当前行评分 < 其他行评分 # 逻辑与后每行求和,得到OverPriced数量 df['OverPriced'] = (salary_lower & score_higher).sum(axis=1) print(df)
这个方法的速度比apply快很多,适合处理十万级以上的数据。
需求一:统计大于/小于当前行的行数
这里默认你是针对某一列的数值进行比较(如果是整行比较,逻辑类似),下面举个例子:
假设我们有一个带Value列的DataFrame,要添加两列:Count_Greater(统计Value中大于当前行的行数)、Count_Less(统计小于当前行的行数)。
方法一:新手友好的apply方式
import pandas as pd df = pd.DataFrame({'Value': [5, 3, 7, 2, 5]}) def count_greater(row): return (df['Value'] > row['Value']).sum() def count_less(row): return (df['Value'] < row['Value']).sum() df['Count_Greater'] = df.apply(count_greater, axis=1) df['Count_Less'] = df.apply(count_less, axis=1) print(df)
结果:
Value Count_Greater Count_Less 0 5 1 2 1 3 3 1 2 7 0 4 3 2 4 0 4 5 1 2
方法二:高效的广播方式
同样,大数据量用这个:
import pandas as pd df = pd.DataFrame({'Value': [5, 3, 7, 2, 5]}) value_vals = df['Value'].values # 生成比较矩阵 greater_matrix = value_vals[:, None] < value_vals # 当前值 < 其他值 → 其他值大于当前值 less_matrix = value_vals[:, None] > value_vals # 当前值 > 其他值 → 其他值小于当前值 df['Count_Greater'] = greater_matrix.sum(axis=1) df['Count_Less'] = less_matrix.sum(axis=1) print(df)
如果是要比较整行所有列都大于/小于当前行,只需要把单列的比较改成多列的逻辑与即可。比如有A和B两列,统计所有行中A和B都大于当前行的行数:
df = pd.DataFrame({'A': [5,3,7], 'B': [2,4,1]}) def count_row_greater(row): return ((df['A'] > row['A']) & (df['B'] > row['B'])).sum() df['Count_Row_Greater'] = df.apply(count_row_greater, axis=1)
内容的提问来源于stack exchange,提问作者Jarrod Holmes




