处理视觉上看起来相同的字符(元音变音)的问题

问题描述 投票:0回答:3

这可能是一个与字符编码相关的更普遍的问题,但由于我在编写两个数据帧的外部连接时遇到了这个问题,所以我将其与 Python 代码示例一起发布。

最重要的是,问题是:为什么

在技术上与
ö
不同,我如何确定两者不仅在视觉上相同,而且在技术上也相同? 如果你在文本编辑器中复制粘贴两个字符并搜索其中一个,你将永远找不到两个!

现在 Python 示例尝试在“文件名”列(此处显示为 CSV 数据)上对两个数据帧进行简单的外部连接:

df1:

filename;abstract
problematic_ö.txt;abc
non-problematic_ö.txt;yxz

df2:

bytes;filename
374;problematic_ö.txt
128;non-problematic_ö.txt

Python代码:

import csv
import pandas as pd

df1 = pd.read_csv('df1.csv', header=0, sep = ';')
df2 = pd.read_csv('df2.csv', header=0, sep = ';')

print(df1) 
print(df2) 

df_outerjoin = pd.merge(df1, df2, how='outer', indicator=True)
df_outerjoin.to_csv('df_outerjoin.csv', sep =';', index=False, header=True, quoting=csv.QUOTE_NONNUMERIC)

print(df_outerjoin)

输出:

#               filename   abstract     bytes        _merge
1      problematic_ö.txt        abc       NaN     left_only
2  non-problematic_ö.txt        yxz     128.0          both
3      problematic_ö.txt        NaN     374.0    right_only

所以有问题的文件名中的 'ö' 不会被识别为与无问题文件名中的 'ö' 相同的字符。

这里发生了什么?

我能做些什么来克服这个问题——我可以通过导入具有特殊编码设置的数据文件来做一些“聪明”的事情,还是我必须做一个愚蠢的搜索和替换?

python character-encoding utf
3个回答
3
投票

在 Unicode 中有多种表示相同字符的方法。在您的情况下,有问题的文件名包含字符“ö”,它实际上由两个 Unicode 代码点表示:“o”(拉丁文小写字母 O)和组合字符“”。 (结合分音符)另一方面,没有问题的文件名使用字符“ö”(带分音符的拉丁文小写字母 O),它由单个 Unicode 代码字符表示。

您可以使用

unicodedata
库-
unicodedata.normalize
.

它是这样工作的

import unicodedata

a = "ö"
b = "ö"
print(a == b)

a = unicodedata.normalize('NFC', a)
b = unicodedata.normalize('NFC', b)

print(a == b)

输出:

False
True

2
投票

问题是带有变音符号的字符通常可以用所谓的组合变音符号或 Unicode 中所谓的预组合字符表示。

problematic_ö.txt
中的第一个实例是
U+006F U+0308
(o 带有变音符号),而
non-problematic_ö.txt
中的第二个实例是预合成的
U+00F6
.

要正常化,试试这个:

import unicodedata

oUml_combDiac = 'ö'
oUml_precomp = 'ö'
oUml_combDiac == oUml_precomp
# False
unicodedata.normalize('NFC', oUml_combDiac) == unicodedata.normalize('NFC', oUml_precomp)
# True

oUml
这里代表“o with umlaut”。)


0
投票

而不是使用

unicodedata
,Pandas 提供以下方法
Series.str.normalize(form)
,所以像:

df1['filename'] = df1['filename'].str.normalize('NFC')
df2['filename'] = df2['filename'].str.normalize('NFC')

在进行外部连接之前。

© www.soinside.com 2019 - 2024. All rights reserved.