【问题标题】:Sort Pandas Series on data descending then on index alphabetically, elegantly按字母顺序对 Pandas Series 进行降序排序,然后按索引优雅地排序
【发布时间】:2018-09-23 16:31:41
【问题描述】:

我正在寻找一种通过数据降序对熊猫系列进行排序的平滑方法,然后是索引升序。我一直在查看文档和 Stackoverflow,但找不到直接的方法。

该系列有大约 5000 个条目,是使用 NLTK 进行 tf-idf 分析的结果。

但是,下面我提供了一个非常小的数据样本来说明问题。

import pandas as pd

index = ['146tf150p', 'anytime', '645', 'blank', 'anything']
tfidf = [1.000000, 1.000000, 1.000000, 0.932702, 1.000000]

tfidfmax = pd.Series(tfidf, index=index)

目前我只是将Series转换为DataFrame,重置索引,进行排序然后设置索引,但我觉得这是一个很大的弯路。

frame = pd.DataFrame(tfidfmax , columns=['data']).reset_index().sort_values(['data','index'], ascending=[False, True]).set_index(['index'])
3.02 ms ± 102 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

期待您的建议!

【问题讨论】:

    标签: python python-3.x pandas sorting numpy


    【解决方案1】:

    您可以为此使用numpy.lexsort

    res = tfidfmax[np.lexsort((tfidfmax.index, -tfidfmax.values))]
    
    print(res)
    
    # 146tf150p    1.000000
    # 645          1.000000
    # anything     1.000000
    # anytime      1.000000
    # blank        0.932702
    # dtype: float64
    

    注意语法中的相反顺序:上面的代码首先按降序排序,然后按索引升序。

    【讨论】:

    • 谢谢!我不知道这个 numpy 功能。还测试了速度:%timeit tfidfmax[np.lexsort((tfidfmax.index, -tfidfmax.values))]。每个循环 211 µs ± 6.86 µs(7 次运行的平均值 ± 标准偏差,每次 1000 个循环)
    【解决方案2】:

    简单:

    In [15]: pd.Series(tfidfmax.sort_values(ascending=False),index=tfidfmax.sort_index().index)
    Out[15]: 
    146tf150p    1.000000
    645          1.000000
    anything     1.000000
    anytime      1.000000
    blank        0.932702
    dtype: float64
    

    或更快的方式:

    In [26]: pd.Series(-np.sort(-tfidfmax),index=np.sort(tfidfmax.index))
    Out[26]: 
    146tf150p    1.000000
    645          1.000000
    anything     1.000000
    anytime      1.000000
    blank        0.932702
    dtype: float64
    
    In [17]: %timeit tfidfmax[np.lexsort((tfidfmax.index, -tfidfmax.values))]
    10000 loops, best of 3: 104 µs per loop
    
    In [18]: %timeit pd.Series(tfidfmax.sort_values(ascending=False),index=tfidfmax.sort_index().index)
    1000 loops, best of 3: 406 µs per loop
    
    In [27]: %timeit pd.Series(-np.sort(-tfidfmax),index=np.sort(tfidfmax.index))
    10000 loops, best of 3: 91.2 µs per loop
    

    【讨论】:

    • 虽然是最快的解决方案,但是要小心,是错误的。尝试从我的答案中检查我的数据。
    • @Steven Van Dorpe 的主要问题是,如果像我对tfidf = [1.000000, 1.000000, 2.000000, 0.932702, 2.000000] 的回答一样更改数据并将您的输入与此答案的输入进行比较,则存在差异。因为这个答案分别排序索引和值。
    • 我试过这个答案,它确实不适用于更复杂的数据。感谢您指出这一点@jezrael!
    【解决方案3】:

    使用函数sorted by ziplists 创建新的Series by zip

    index = ['146tf150p', 'anytime', '645', 'blank', 'anything']
    tfidf = [1.000000, 1.000000, 2.000000, 0.932702, 2.000000]
    
    a = list(zip(*sorted(zip(index, tfidf),key=lambda x:(-x[1],x[0]))))
    
    #if input is Series
    #a = list(zip(*sorted(zip(tfidfmax.index,tfidfmax),key=lambda x:(-x[1],x[0]))))
    s = pd.Series(a[1], index=a[0])
    print (s)
    645          2.000000
    anything     2.000000
    146tf150p    1.000000
    anytime      1.000000
    blank        0.932702
    dtype: float64
    

    【讨论】:

    • 谢谢!角度不错。您知道是否有某种方法可以使用 sort_values 并引用索引? IE。 tfidf.sort_values(引用值引用索引,升序=[False, True])。有点像 lexsort,但在 pandas 中。
    • @Steven Van Dorpe 遗憾的是尚未实施。
    猜你喜欢
    • 2020-03-19
    • 1970-01-01
    • 1970-01-01
    • 2016-02-15
    • 1970-01-01
    • 2021-12-28
    • 1970-01-01
    • 2021-12-20
    • 2011-01-15
    相关资源
    最近更新 更多