You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

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)

如果是要比较整行所有列都大于/小于当前行,只需要把单列的比较改成多列的逻辑与即可。比如有AB两列,统计所有行中AB都大于当前行的行数:

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

火山引擎 最新活动