繁体   English   中英

对数据框中的列进行排名的更有效方法

[英]More efficient way to rank columns in a dataframe

目前我有一个数据框,我对每列的值进行排名并将它们输出到一个新的数据框中。 示例代码如下:

df = pd.DataFrame(np.random.randint(0, 500, size=(500, 1000)), columns=list(range(0, 1000)))

ranking = pd.DataFrame(range(0, 500), columns=['Lineup'])

ranking = pd.concat([ranking, df[range(0, 1000)].rank(ascending=False, method='min')],
                        axis=1)

df 是值的数据框,每列标题是一个整数,每连续列增加 1。 排名首先由“Lineup”以单列作为标识符创建,然后数据帧“df”被连接并同时排名。

现在的问题是,这是最快的方法吗? 当有数万列和数百行时,这可能比我希望的要长得多。 有没有办法使用列表理解来加快速度,或者使用某种其他方法来输出列表、字典、数据框或其他任何我可以用于未来步骤的东西。

谢谢

您可以使用Numba JIT 更高效地并行计算。 这个想法是并行计算每列的排名。 这是结果代码:

# Equivalent of df.rank(ascending=False, method='min')
@nb.njit('int32[:,:](int32[:,:])', parallel=True)
def fastRanks(df):
    n, m = df.shape
    res = np.empty((n, m), dtype=np.int32)

    for col in nb.prange(m):
        dfCol = -df[:, col]
        order = np.argsort(dfCol)

        # Compute the ranks with the min method
        if n > 0:
            prevVal = dfCol[order[0]]
            prevRank = 1
            res[order[0], col] = 1

            for row in range(1, n):
                curVal = dfCol[order[row]]
                if curVal == prevVal:
                    res[order[row], col] = prevRank
                else:
                    res[order[row], col] = row + 1
                    prevVal = curVal
                    prevRank = row + 1

    return res

df = pd.DataFrame(np.random.randint(0, 500, size=(500, 1000)), columns=list(range(0, 1000)))
ranking = pd.DataFrame(range(0, 500), columns=['Lineup'])
ranking = pd.concat([ranking, pd.DataFrame(fastRanks(df[range(0, 1000)].to_numpy()))], axis=1)

在我的 6 核机器上,排名的计算速度大约快 7 倍 整体计算受限于缓慢的pd.concat

您可以通过使用“Lineup”列直接构建fastRanks的输出来进一步提高整体计算的速度。 必须从 Numba 函数生成的 Numpy 数组中手动​​设置数据框列的名称。 请注意,此优化要求所有列的类型相同,您的示例就是这种情况。

请注意,出于性能考虑,此解决方案中的等级为int32类型(因为此处不需要float64 )。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM