【问题标题】:pandas sort rows by index using a custom functionpandas 使用自定义函数按索引对行进行排序
【发布时间】:2018-02-05 16:16:37
【问题描述】:

我经常需要处理行名(pandas 中的索引)类似于 [a-z][0-9]+ 类型的数据框(例如 'a20','a21',... 或 'b1','b11','b2 ',...)

我希望能够仅根据数字对行进行排序。从我可以收集到的 API 中,df.sort_index() 没有使用我可以定义排序函数的函数参数。

有没有一种简洁的方法可以在创建数据框时不移除初始字符来实现这一点?

【问题讨论】:

  • 或许你可以使用reindex。
  • 我认为目前最好的方法是从索引中构造一列,删除字母前缀,然后按此排序。
  • 我觉得最好的理论方法是拥有一个字符串列和一个整数列的多索引,然后您可以使用标准的 pandas 排序和功能。但是,当前的答案之一很可能是一个更好的实用答案,因为多索引会带来更多的复杂性。
  • 我同意@HaleemurAli,但前提是索引的数字部分是唯一标识符。 IE。您想如何处理 A25 和 B25(如果可能的话)。

标签: python pandas


【解决方案1】:

您可以使用extract,转换为int并通过argsort获取排序值的位置,最后使用iloc

(借用@Dark的数据):

df = df.iloc[df.index.str.extract('(\d+)', expand=False).astype(int).argsort()]
print (df)
     0
a5   5
a6   6
a10  2
a11  3
b11  7
a12  1
b12  8
a15  4

说明

df = pd.DataFrame([1,2,3,4,5,6,7,8],index=['a12','a10','a11','a15','a5','a6','b11','b12'])
print (df)
     0
a12  1
a10  2
a11  3
a15  4
a5   5
a6   6
b11  7
b12  8

第一个extract所有整数:

print (df.index.str.extract('(\d+)', expand=False))
Index(['12', '10', '11', '15', '5', '6', '11', '12'], dtype='object')

投射到integers:

print (df.index.str.extract('(\d+)', expand=False).astype(int))
Int64Index([12, 10, 11, 15, 5, 6, 11, 12], dtype='int64')

通过argsort获取排序值的位置:

print (df.index.str.extract('(\d+)', expand=False).astype(int).argsort())
[4 5 1 2 6 0 7 3]

iloc 的最后选择值:

print (df.iloc[df.index.str.extract('(\d+)', expand=False).astype(int).argsort()])
     0
a5   5
a6   6
a10  2
a11  3
b11  7
a12  1
b12  8
a15  4

【讨论】:

  • 您能详细说明一下这是做什么的吗?它似乎工作很酷,但我希望能够理解它的作用:)
【解决方案2】:

通过使用natsort 按索引列表排序然后reindex

df=pd.DataFrame({'v':[1,2,3]},index=['b1','b11','b2'])

from natsort import natsorted, ns


df.reindex(natsorted(df.index.tolist(), alg=ns.IGNORECASE))

Out[795]: 
     v
b1   1
b2   3
b11  2

【讨论】:

  • 你有点快
  • @Dark 是的,只是一点点:-)
【解决方案3】:

您可以使用排序和重新索引,即

df = pd.DataFrame([1,2,3,4,5,6,7,8],index=['a12','a10','a11','a15','a5','a6','b11','b12'])

import re
df.reindex(sorted(df.index,key=lambda x: re.sub('[A-z]','',x)))


    0
a10  2
a11  3
b11  7
a12  1
b12  8
a15  4
a5   5
a6   6

【讨论】:

  • 我认为需要转换为int :)
猜你喜欢
  • 2021-12-01
  • 1970-01-01
  • 2014-06-10
  • 2016-10-22
  • 1970-01-01
  • 2022-08-19
  • 2019-05-26
  • 2021-10-03
  • 2017-06-16
相关资源
最近更新 更多