熊猫sort_values提供意外结果

时间:2019-08-02 07:06:54

标签: pandas sorting

我很难理解为什么两个sort_by命令之间的排序顺序不同。该示例直接取自我的数据。根据文档,sort_values应该按指定的轴(默认轴= 0)和指定的(by =)索引/列进行排序。

我的看法是,两个sort_values命令应该给出相同的结果,因为唯一的区别是第一个和最后一个字符,这对于指定列中的每个值都是相同的。

import pandas as pd

dc=[['@10309000_0010@','!10309000_0010!'],
      ['@10309000_0011@','!10309000_0011!'],
      ['@10309000_0012@','!10309000_0012!'],
      ['@10309000_00@','!10309000_00!']]
df=pd.DataFrame(dc,columns=['c1','c2'])
df

数据:

                 c1              c2
0   @10309000_0010@ !10309000_0010!
1   @10309000_0011@ !10309000_0011!
2   @10309000_0012@ !10309000_0012!
3   @10309000_00@   !10309000_00!

按列c1排序:

df.sort_values(by='c1')

结果首先是样品10309000_0010:

                 c1              c2
0   @10309000_0010@ !10309000_0010!
1   @10309000_0011@ !10309000_0011!
2   @10309000_0012@ !10309000_0012!
3   @10309000_00@   !10309000_00!

按c2列排序:

df.sort_values(by='c2')

结果,样品10309000_00现在是第一个:

                 c1              c2
3   @10309000_00@   !10309000_00!
0   @10309000_0010@ !10309000_0010!
1   @10309000_0011@ !10309000_0011!
2   @10309000_0012@ !10309000_0012!

我想念什么吗?

2 个答案:

答案 0 :(得分:3)

这是字符串如何工作的一般效果:每个字符corresponds to a numeric value

>>> {ch: ord(ch) for ch in '1!@'}
{'1': 49, '!': 33, '@': 64}

排序时,数字值确定排序。由于64 > 49 > 33的存在,因此它也拥有'@' > '1' > '!'

请注意,字符 '1'没有顺序1。该字符串与它表示的数字不同。同样,字符串"@10309000_0010@"的顺序不是“ @包围的数字”,而是“字符串'@'10,...”的顺序。 。使用lexicographic ordering比较字符串-这类似于比较tuple的方式。重要的是,这与前导位置进行比较,不匹配后的尾随位置将被忽略:

>>> "2" > "3"   # 2 > 3 decides comparison
False
>>> "2" > "1"   # 2 > 1 decides comparison
True
>>> "2" > "10"  # 2 > 1 decides comparison
True

如果将"@10309000_0012@""@10309000_00@"进行比较,则'1''@'在位置12的差将决定匹配。如果未检查较长的字符串,则尾随"2@"。将'@'替换为'!'时也是如此。换句话说,它可以归结为'@' > '1' > '!'

答案 1 :(得分:0)

问题是!> 1> @的相对优先级。因此,按c1排序在[12]中将所有带有'1'的内容置于在[12]中带有'@'的所有内容中,但按c2进行排序的所有内容都将带有'! [12]中的所有内容都以[1]中的“ 1”开头,这间接地给了我我想要的答案。

s=pd.Series(['@','1','!'])

2    !
1    1
0    @

我认为natsort可能更强大。

(对深夜的混乱感到抱歉,再次感谢anky_91。)