如何将混合字节/字符串的pandas.Series转换/解码为字符串或utf-8编码。

3

我希望解决以下两种可能情况的问题:

  1. 在事先不知道字符串序列是UTF-8还是字节的情况下。

  2. pd.Series中的字符串是混合字节和UTF-8/的情况。

我猜这两种情况有相同的解决方案。

目前的情况为:

b = pd.Series(['123', '434,', 'fgd', 'aas', b'442321'])
b.str.decode('utf-8')

如果字符串已经是UTF-8格式,则将其转换为NaNs。或者它们会自动转换为ASCII码?例如,我可以在decode函数中使用error参数,以便字符串在已经是UTF-8编码时保持“未解码”吗?文档字符串似乎没有提供太多信息。

还有没有更好的方法来实现这一点?

另外,在pandas中是否有类似于.str.decode的字符串方法,当一个字符串是bytesUTF-8时只返回True/False?

编辑:

我能想到的一个选项是:

b = pd.Series(['123', '434,', 'fgd', 'aas', b'442321'])
converted = b.str.decode('utf-8')
b.loc[~converted.isnull()] = converted

那么这是推荐的方式吗?看起来有点绕。我猜更优雅的方法实际上只是一种检查一个系列中所有元素是否为字节的str的方式,并返回一个布尔数组,其中是这种情况。

2个回答

3

对于大型系列数据来说,这肯定会减慢速度,但您可以通过传递一个可调用的三元表达式来解决:

>>> b.apply(lambda x: x.decode('utf-8') if isinstance(x, bytes) else x)                                                                                                                                                                                      
0       123
1      434,
2       fgd
3       aas
4    442321
dtype: object

看一下.str.decode()的源代码很有启发性——它只是在Series上应用_na_map(f, arr)函数,其中函数ff = lambda x: x.decode(encoding, errors)。因为str本来就没有“decode”方法,所以该错误将变成NaN。这发生在str_decode()中。
>>> from pandas.core.strings import str_decode                                                                                                                                                                                                               
>>> from pandas.core.strings import _cpython_optimized_encoders                                                                                                                                                                                              

>>> "utf-8" in _cpython_optimized_encoders                                                                                                                                                                                                                   
True
>>> str_decode(b, "utf-8")                                                                                                                                                                                                                                   
array([nan, nan, nan, nan, '442321'], dtype=object)

>>> from pandas.core.strings import _na_map                                                                                                                                                                                                                  
>>> f = lambda x: x.decode("utf-8")                                                                                                                                                                                                                          
>>> _na_map(f, b)                                                                                                                                                                                                                                            
array([nan, nan, nan, nan, '442321'], dtype=object)

1

这个问题在git中仍然存在。

由以下代码行引起

  except (TypeError, AttributeError):
         return na_value
修复添加 fillna
b.str.decode('utf-8').fillna(b)
Out[237]: 
0       123
1      434,
2       fgd
3       aas
4    442321
dtype: object

唯一的问题是这将“掩盖由于编码而引起的实际错误”。如果您有一个无法解码为UTF-8的Latin-1字节,则会替换为其原始值,而这可能是无意的。 - Brad Solomon
谢谢你的回答,两个都很有教育意义和有用,我不确定哪个是最好的。同时感谢你提出Git问题,这似乎是需要解决的一个问题。 - Marses

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接