【问题标题】:pandas sort with capital letters熊猫用大写字母排序
【发布时间】:2021-01-18 18:24:45
【问题描述】:

运行此代码:

df = pd.DataFrame(['ADc','Abc','AEc'],columns = ['Test'],index=[0,1,2])
df.sort(columns=['Test'],axis=0, ascending=False,inplace=True)

返回排序为:[Abc, AEc, ADc] 的数据框列。 ADc应该在AEc之前,这是怎么回事?

【问题讨论】:

  • 这对我来说似乎是一个错误,我可以在 pandas 0.16.0、numpy 1.9.1 python 3.4.3 64-bit 上重现它
  • 确认老熊猫的错误​​0.14.0

标签: sorting pandas


【解决方案1】:

我不认为这是熊猫错误。这似乎只是 python 排序算法使用混合大小写字母(区分大小写)的方式 - look here

因为当你这样做时:

In [1]: l1 = ['ADc','Abc','AEc']
In [2]: l1.sort(reverse=True)
In [3]: l1
Out[3]: ['Abc', 'AEc', 'ADc']

因此,由于显然无法使用 pandas 排序方法控制排序算法,因此只需使用该列的小写版本进行排序并稍后将其删除:

In [4]: df = pd.DataFrame(['ADc','Abc','AEc'], columns=['Test'], index=[0,1,2])
In [5]: df['test'] = df['Test'].str.lower()
In [6]: df.sort(columns=['test'], axis=0, ascending=True, inplace=True)
In [7]: df.drop('test', axis=1, inplace=True)
In [8]: df
Out[8]:
  Test
1  Abc
0  ADc
2  AEc

注意:如果您希望列按字母顺序排序,ascending 参数必须设置为 True

编辑:

正如DSM 建议的那样,为避免创建新的帮助列,您可以这样做:

df = df.loc[df["Test"].str.lower().order().index]

更新:

正如weatherfrog 所指出的,对于较新版本的pandas,正确的方法是.sort_values()。所以上面的单行就变成了:

df = df.loc[df["Test"].str.lower().sort_values().index]

【讨论】:

  • 是的,这是 Python 的行为。或者,您可以执行df.loc[df["Test"].str.lower().order().index] 之类的操作,以避免创建临时列。 OP 仍然需要决定“AbC”和“ABc”应该如何相对于彼此排序。
  • 我从来不知道,这是有见地+1
  • 上面的一行不再适用于较新版本的 Pandas,因为 Series.order() 现在是 Series.sort_values()。所以这转换为df.loc[df["Test"].str.lower().sort_values().index]
【解决方案2】:

使用 DataFrame.sort_valueskey 参数,因为pandas >= 1.1.0

我们现在可以在 sort_values 方法中传递字符串的自定义函数或任何其他自定义键:

df = pd.DataFrame(['ADc','Abc','AEc'],columns = ['Test'],index=[0,1,2])
print(df)

  Test
0  ADc
1  Abc
2  AEc
df.sort_values(by="Test", key=lambda x: x.str.lower())

  Test
1  Abc
0  ADc
2  AEc

【讨论】:

    【解决方案3】:

    这是一个如何使用reindex 对多列进行排序的示例,扩展自@Zero 的答案here。我们想先按第二列 (SORT_INDEX1) 对示例数据帧进行排序,然后是第一列 (SORT_INDEX2)。此示例使用不区分大小写的排序对辅助列 (SORT_INDEX2) 进行排序,然后使用默认的区分大小写排序对主列 (SORT_INDEX1) 进行排序。

    import pandas as pd
    
    df = pd.DataFrame([['q', '1'],['a', '1'],['B', '1'],['C', '1'],
                       ['q', '0'],['a', '0'],['B', '0'],['C', '0']])
    
    SORT_INDEX1 = 1
    SORT_INDEX2 = 0
    
    # Cannot change sorting algorithm used internally by pandas.
    df_default = df.sort_values(by=[SORT_INDEX1, SORT_INDEX2])
    
    # Use tuple of (index, value to sort by) to get a list of sorted indices, obtained through unzipping.
    df_new = df.reindex(list(zip(*sorted(zip(df.index, df[SORT_INDEX2]), key=lambda t: t[1].lower())))[0])
               .sort_values(by=SORT_INDEX1)
    
    print('Original dataframe:')
    print(df)
    
    print('Default case-sensitive sort:')
    print(df_default)
    
    print('Case-insensitive sort:')
    print(df_new)
    

    输出:

    Original dataframe:
       0  1
    0  q  1
    1  a  1
    2  B  1
    3  C  1
    4  q  0
    5  a  0
    6  B  0
    7  C  0
    Default case-sensitive sort:
       0  1
    6  B  0
    7  C  0
    5  a  0
    4  q  0
    2  B  1
    3  C  1
    1  a  1
    0  q  1
    Case-insensitive sort:
       0  1
    5  a  0
    6  B  0
    7  C  0
    4  q  0
    1  a  1
    2  B  1
    3  C  1
    0  q  1
    

    (More info on unzipping)

    编辑:抱歉,第二个排序不适用于较大的数据集。不保留辅助列的顺序。这种方法可以很好地按一列排序,但我仍然需要找到一种可靠而简洁的方法来对两列进行排序。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-01-06
      • 2020-08-24
      • 1970-01-01
      • 2020-12-24
      • 2018-10-02
      • 2013-02-01
      • 2018-04-13
      • 2018-12-14
      相关资源
      最近更新 更多