熊猫排名为负整数和正整数,多列

时间:2019-01-25 13:13:39

标签: python pandas math

我不是数学家,我是财务人员,面临的问题最好用以下方式描述: 我正在寻找有关如何对两个整数序列进行排名的建议,其中一个整数具有正负两个域,另一个整数只有一个正域。

期望X的高正值,不需要高负值。

Y限制为正数,不希望有高值,而希望有低值。

到目前为止,我最好的猜测是:

在正域中,该比率有意义:X / Y

在负域(1 / X * Y)往往是合理的,但我怀疑它强加了不对称性。

让我们假设这是X和Y的理想排序序列

X, Y, rank
10,100, 6
10,1000, 5.5
1,100, 5.5
1,1000, 4
-1,100, 3
-1,1000, 2.5
-10,100, 2.5
-10,1000, 1

5.5和2.5在数值和概念上相似(差异)。

您是否可以想到一个用于对逻辑进行排名和捕获的功能?

一个硬性限制是,正X总是比负X更好,因此X的负值永远不能排名高于X的正值。

4 个答案:

答案 0 :(得分:1)

如果您知道X序列的最小值,那么最好使用以下分数:

(X + Xmin)/Y # Adding the minimal value as an offset is a standard procedure to obtain only positive values. 

如果您想走得更远,甚至可以执行以下命令来标准化X和Y:

X = (X + Xmin) / Xmax
Y = (Y + Ymin) / Ymax

然后执行得分= X / Y

答案 1 :(得分:1)

我使用了series.rank(),如下所示:

df['new_rank']=df.X.rank(method='dense',ascending=True)+df.Y.rank(method='dense',ascending=False)-1
print(df)

    X     Y  rank  new_rank
0  10   100   6.0       5.0
1  10  1000   5.5       4.0
2   1   100   5.5       4.0
3   1  1000   4.0       3.0
4  -1   100   3.0       3.0
5  -1  1000   2.5       2.0
6 -10   100   2.5       2.0
7 -10  1000   1.0       1.0

提供的链接中的文档说明。

答案 2 :(得分:0)

您使用X/Y的假设(如果Y接受0,请确保您使用X / 1 + Y)是正确的。现在问题是您对X和Y的重视程度如何?我的意思是,假设(aX)* (b*(1/y))现在ab上的所有事情都重要。

由于X的重要性随着其值的增加而增加,所以您甚至可以使用x ^ 3并惩罚较高的否定项并奖励较高的肯定项。

来到y,1/(1+y^2)如果(y接受0,未定义1/0,则将其加1。)

答案 3 :(得分:0)

您还在寻找解决方案吗?如果它仍然相关,我可以发布。简而言之,您首先需要分离问题 a) 拆分指标和 b) 计算分数。指标高到低的比率排名越高,排名越高(例如毛利率、ROE、ROA)。对于这个组,您无需担心负数,因为当按降序排序时,它们将获得您期望的适当权重。第二组比率需要分批到低到高类别中(例如市盈率、市账率等),您应该对它们进行预处理,以惩罚该子项的负数团体。这需要更改原始数据,因此您应该为预处理和排名制作 df 的副本。我建议使用 minmax 缩放作为分数,因为使用对 minmax 缩放比例的排序,只需对这个子组进行小幅调整即可以适当的方式对其进行评分。这是处理预处理和对低到高组中的指标进行评分的部分解决方案。注意:如果你真的想给 NaN 值一个平均值,你可以在我这里处理负值的函数的下方或上方添加另一个 lambda 函数。此处的负值与最高值相加,因此将获得最低分。在我将其用于 49 个财务比率时,我离开 NaN 并只对分数求和。否则,即使缺少大部分数据,一行或公司也可以获得合理的值,而对于分数的总和,它在所有比率上仍然显得不那么有吸引力。 `将熊猫导入为 pd 将 numpy 导入为 np def main():

df = pd.DataFrame({'A':[-14.00,90.20,np.nan,96.27,91.21],
                   'B':[103.02,-17.26,110.35,114.23,114.68], 
                   'C':['big','small','big','small','small']})
mycolumns=['A', 'B']
df_sub=pd.DataFrame(columns=mycolumns)      #used to protect the original data
for mycol in mycolumns:
    df_sub[mycol]=(df[mycol])
    cmax=df_sub[mycol].max()
    df_sub[mycol] = df_sub[mycol].apply(lambda x : x if x > 0 else (cmax-x))
    df[f'{mycol} Score'] = 1-(df_sub[mycol] - df_sub[mycol].min()) / (df_sub[mycol].max() - df_sub[mycol].min())
    print(f'Original Data with Scores:\n {df},\nScaled Data: \n {df_sub}')`