【问题标题】:Sorting pandas dataframe with German Umlaute使用德语变音符号对 pandas 数据框进行排序
【发布时间】:2019-08-07 01:53:54
【问题描述】:

我有一个数据框,我想通过 sort_values 在一列上进行排序。

问题是单词的第一个字母是德语变音符号。

就像苏黎世的 Österreich。

这将排序到苏黎世,Österreich。 应该是排序 Österreich, Zürich。

Ö应该在N和O之间。

我发现了如何在 python 中使用语言环境和 strxfrm 来处理列表。 我可以以某种方式直接在 pandas 数据框中执行此操作吗?

编辑: 谢谢你。 Stef 示例工作得很好,不知何故我有数字,他的版本与我的现实生活中的 Dataframe 示例不兼容,所以我使用了 alexey 的想法。 我做了以下,也许你可以缩短这个..:


df = pd.DataFrame({'location': ['Österreich','Zürich','Bern', 254345],'code':['ö','z','b', 'v']})

#create index as column for joining later
df = df.reset_index(drop=False)

#convert int to str
df['location']=df['location'].astype(str)

#sort by location with umlaute
df_sort_index = df['location'].str.normalize('NFD').sort_values(ascending=True).reset_index(drop=False)

#drop location so we dont have it in both tables
df = df.drop('location', axis=1)

#inner join on index
new_df = pd.merge(df_sort_index, df, how='inner', on='index')

#drop index as column
new_df = new_df.drop('index', axis=1)

【问题讨论】:

  • 你检查过 alexey 方法的输出吗?我得到 Ö 或 ü 的变音点不是在 O 或 u 上,而是在 IDLE 中的一个空格上。在控制台上,它会使用退格键将它们放在 O 或 u 上,但下一列不再对齐。 Firefox 还显示它们发生了变化(Österreich 而不是 Österreich)所以你必须在最终结果中恢复规范化。
  • 对不起,我不确定您的确切意思,我将结果导出到 Excel,它们看起来还不错?

标签: python pandas sorting dataframe locale


【解决方案1】:

您可以将sorted 与区域感知排序函数一起使用(在我的示例中,setlocale 返回'German_Germany.1252')对列值进行排序。 棘手的部分是对所有其他列进行相应的排序。 一个有点笨拙的解决方案是临时将索引设置为要排序的列,然后在正确排序的索引值上重新索引并重置索引。

import functools
import locale
locale.setlocale(locale.LC_ALL, '')
df = pd.DataFrame({'location': ['Österreich','Zürich','Bern'],'code':['ö','z','b']})

df = df.set_index('location')
df = df.reindex(sorted(df.index, key=functools.cmp_to_key(locale.strcoll))).reset_index()

打印输出(df):

     location code
0        Bern    b
1  Österreich    ö
2      Zürich    z


混合类型列的更新 如果要排序的列是混合类型(例如字符串和整数),那么您有两种可能性:

a) 将列转换为字符串,然后按上述方式排序(结果列将是所有字符串):

locale.setlocale(locale.LC_ALL, '')
df = pd.DataFrame({'location': ['Österreich','Zürich','Bern', 254345],'code':['ö','z','b','v']})
df.location=df.location.astype(str)
df = df.set_index('location')
df = df.reindex(sorted(df.index, key=functools.cmp_to_key(locale.strcoll))).reset_index()
print(df.location.values)
# ['254345' 'Bern' 'Österreich' 'Zürich']

b)对转换为字符串的列的副本进行排序(结果列将保留混合类型)

locale.setlocale(locale.LC_ALL, '')
df = pd.DataFrame({'location': ['Österreich','Zürich','Bern', 254345],'code':['ö','z','b','v']})
df = df.set_index(df.location.astype(str))
df = df.reindex(sorted(df.index, key=functools.cmp_to_key(locale.strcoll))).reset_index(drop=True)
print(df.location.values)
# [254345 'Bern' 'Österreich' 'Zürich']

【讨论】:

  • @joeagency 我更新了混合类型列的答案
  • 嘿,这适用于示例 thx。由于在我的现实世界数据中我有重复项,我必须制作一个没有重复项的新 DF,以便我可以将它们用作索引和排序,然后再加入等......至少这两种解决方案都适用于我的数据。跨度>
【解决方案2】:

你可以使用unicode NFD范式

>>> names = pd.Series(['Österreich', 'Ost', 'S', 'N'])
>>> names.str.normalize('NFD').sort_values()
3              N
1            Ost
0    Österreich
2              S
dtype: object

# use result to rearrange a dataframe
>>> df[names.str.normalize('NFD').sort_values().index]

这不是您想要的,但是为了正确排序,您需要语言知识(例如您提到的语言环境)。

NFD 使用两个符号表示变音符号,例如Ö 变为 O\xcc\x88 (你可以看到与names.str.normalize('NFD').encode('utf-8') 的区别)

【讨论】:

  • 我认为 OP 要求按一列的值对整个数据帧进行排序,而不仅仅是这一列的值。除了 NFDstr.normalize 的 +1,以前不知道。
  • 您可以使用生成的索引重新排列数据框
猜你喜欢
  • 2021-05-31
  • 1970-01-01
  • 2016-04-25
  • 1970-01-01
  • 1970-01-01
  • 2011-11-07
  • 2013-08-05
  • 2016-01-21
  • 2013-06-05
相关资源
最近更新 更多