【问题标题】:Python length is 4x too long (from array decoded to utf-8)Python 长度是 4x 太长(从数组解码到 utf-8)
【发布时间】:2020-12-13 12:49:38
【问题描述】:

我有一个np.array 的字符,看起来像

[['a' 'c' 'b' 'a' 'd' 'd' 'b' 'c']
 ['a' 'd' 'c' 'd' 'b' 'c' 'a' 'b']]

但是,当我使用 .tostring() 时,它们开始使用 \x00 字节码看起来很有趣。

所以我使用了.decode('utf-8'),现在它们看起来就像我想要的一样。

result['mytxt'].apply(lambda x: x.tostring().decode("utf-8"))

但是,当我执行 len() 函数来计算它们的长度时,计数的长度是 4 倍。

关于在哪里做出最好的改变以防止这种情况发生有什么想法吗?

这感觉有点老套:

result['pct_a_in_mytxt'].apply(lambda s: str(s).count('a') / (len(s) / 4 ))

编辑:添加了一些代码来重现

import pandas as pd
import numpy as np

fakejson = [
 {   "territory": "A",   "salesqty": 98 },
 {   "territory": "A",   "salesqty": 84 },
 {   "territory": "A",   "salesqty": 56 },
 {   "territory": "A",   "salesqty": 41 },
 {   "territory": "A",   "salesqty": 82 },
 {   "territory": "B",   "salesqty": 79 },
 {   "territory": "B",   "salesqty": 36 },
 {   "territory": "B",   "salesqty": 1 },
 {   "territory": "B",   "salesqty": 52 },
 {   "territory": "B",   "salesqty": 12 },
 {   "territory": "B",   "salesqty": 17 }
]

df = pd.DataFrame(fakejson)

grouped = df.groupby(['territory'])
dfsax = grouped[['territory','salesqty']].aggregate(lambda x: tuple(x))

dfsax['sequence_len'] = dfsax['salesqty'].apply(lambda x: len(x))


from pyts.approximation import SymbolicAggregateApproximation
n_bins = 5
sax = SymbolicAggregateApproximation(n_bins=n_bins, strategy='quantile')


unique_lens = dfsax.sequence_len.unique()

result = pd.DataFrame()

for l in unique_lens:
    if l >= n_bins:
        filtered = dfsax[(dfsax['sequence_len']==l)].copy()
        if len(filtered) > 0:
            filtered['sax_txt_array'] = filtered['salesqty'].apply(lambda x: sax.fit_transform(np.array(x).reshape(1,-1)))
            result = result.append(filtered)

# peek at the result as an array 
result[['sax_txt_array']]

# now try to make it a string
result['sax_txt_not_decoded'] = result['sax_txt_array'].apply(lambda x: x.tostring())

# decode to make it readable
result['sax_txt_decoded'] = result['sax_txt_array'].apply(lambda x: x.tostring().decode('utf-8'))

# count each new string and get the wrong result
result['sequence_len_2'] = result['sax_txt_decoded'].apply(lambda x: len(x))

result


+-----------+--------------+----------------------+---------------------------------------------------+-----------------+----------------+
| territory | sequence_len |    sax_txt_array     |                sax_txt_not_decoded                | sax_txt_decoded | sequence_len_2 |
+-----------+--------------+----------------------+---------------------------------------------------+-----------------+----------------+
| A         |            5 | [[e, d, b, a, c]]    | b'e\x00\x00\x00d\x00\x00\x00b\x00\x00\x00a\x00... | edbac           |             20 |
| B         |            6 | [[e, c, a, d, a, b]] | b'e\x00\x00\x00c\x00\x00\x00a\x00\x00\x00d\x00... | ecadab          |             24 |
+-----------+--------------+----------------------+---------------------------------------------------+-----------------+----------------+

【问题讨论】:

  • 你算before还是after解码?
  • 请出示完整的 MCVE。您的描述不够精确,无法复制您的步骤。
  • result 是熊猫数据框吗?熊猫标签在哪里?
  • 具有 'U1' dtype 的 numpy 数组对每个元素使用 4 个字节。如果 dtype 是 'S1',它使用 1 个字节。 'U' 表示 unicode','S' 表示字节串。pandas 使用对象 dtype 表示字符串,使用默认的 python unicode 字符串(python 3)。

标签: python pandas string numpy


【解决方案1】:

如果不运行所有代码(我没有pyts),看起来sax_txt_array 列的一个单元格是一个numpy 字符串数组。

例如:

In [32]: arr = np.array([['e', 'd', 'b', 'a', 'c']])                                                 
In [33]: arr                                                                                         
Out[33]: array([['e', 'd', 'b', 'a', 'c']], dtype='<U1')
In [34]: arr.tostring()                                                                              
/usr/local/bin/ipython3:1: DeprecationWarning: tostring() is deprecated. Use tobytes() instead.
  #!/usr/bin/python3
Out[34]: b'e\x00\x00\x00d\x00\x00\x00b\x00\x00\x00a\x00\x00\x00c\x00\x00\x00'
In [35]: len(_)                                                                                      
Out[35]: 20
In [36]: arr.astype('S1')                                                                            
Out[36]: array([[b'e', b'd', b'b', b'a', b'c']], dtype='|S1')
In [37]: arr.astype('S1').tostring()                                                                 
/usr/local/bin/ipython3:1: DeprecationWarning: tostring() is deprecated. Use tobytes() instead.
  #!/usr/bin/python3
Out[37]: b'edbac'

在 py3 中,字符串是 unicode,其字节数可变(每个字符最多 4 个)。在numpy's 版本中,所有字符都使用4 个字节,因此tostring 的长度为4*#char。

【讨论】:

    猜你喜欢
    • 2011-01-01
    • 1970-01-01
    • 2023-03-25
    • 2016-11-26
    • 1970-01-01
    • 1970-01-01
    • 2019-09-15
    • 1970-01-01
    • 2018-10-08
    相关资源
    最近更新 更多