numpy结构阵Pandas测向:无法获取列的unicode或字符串类型(仅对象)

iklwldmw  于 2022-12-28  发布在  其他
关注(0)|答案(3)|浏览(130)

我从一个软件系统中提取数据,它给了我一个numpy结构化数组。我将其转换为panda DataFrame来工作,然后需要将其转换回结构化数组,以便将其推回原始系统。字符串/文本数据在数组中显示为unicode列,并在DF中被描述为对象。我一直在尝试找出如何将其恢复为unicode或string。无论是在DF中,还是在结束数组中,但是遇到了麻烦。为了问一个问题,我如何让DF列的数据类型为unicode/string?
这是我正在尝试的,列'地区'是我的重点之一:

import pandas as pd
import numpy as np
arr = array([(1, u'01', 7733855, 0), (2, u'01', 7733919, 1244),
       (3, u'01', 7732571, 1236), (4, u'01', 7732387, 1234),
       (5, u'01', 7733327, 1239), (6, u'01', 7733755, 1241),
       (7, u'01', 7732571, 1236), (8, u'01', 7733923, 0),
       (9, u'01', 7733327, 1239), (10, u'01', 7733755, 1241)], 
      dtype=[('hru_id_nat', '<i4'), ('region', '<U255'), ('POI_ID', '<i4'), ('hru_segment', '<i4')])

然后我就可以做一个DF:

df = pd.DataFrame(arr)
df.dtypes

显示'region'具有object数据类型:

hru_id_nat      int32
region         object
POI_ID          int32
hru_segment     int32
dtype: object

我尝试在转换为DF时指定数据类型,但没有完全得到:

n = list(arr.dtype.names)
t = [i[0].name for i in arr.dtype.fields.values()]
dt = [(i, j) for i, j in zip(n, t)]
dt

得到:

[('hru_id_nat', 'int32'),
 ('region', 'unicode8160'),
 ('POI_ID', 'int32'),
 ('hru_segment', 'int32')]

当我尝试使用dt规范创建DF时,这会抛出一个错误

df = pd.DataFrame(arr, dt)

如果我尝试这些也没用:

dt[1] = ('region', 'unicode')
dt[1] = ('region', 'str')
dt[1] = ('region', np.str)

我还尝试了convert_type()(基于this post)和df['region'] = df['region'].astype(np.str)(基于this post),但似乎都没有改变DF报告的dtype。
非常感谢您的意见。

8wigbo56

8wigbo561#

除非我误解了(这是完全可能的),我认为你在这里有一个XY problem...PandasDataFrame永远不会告诉你它有任何dtype为'unicode'的东西。但是你的unicode数据存储为'object'是非常安全的。所有的字符串数据都存储为'object' dtype 1。
从DataFrame转换后恢复unicode dtype的问题应该不难,当我使用to_records方法转换DataFrame时,我得到的字符串数据('region')是'O'类型,这可能是您所做的:

>>> a = df.to_records()
>>> a
rec.array([(0L, 1, u'01', 7733855, 0), (1L, 2, u'01', 7733919, 1244),
       (2L, 3, u'01', 7732571, 1236), (3L, 4, u'01', 7732387, 1234),
       (4L, 5, u'01', 7733327, 1239), (5L, 6, u'01', 7733755, 1241),
       (6L, 7, u'01', 7732571, 1236), (7L, 8, u'01', 7733923, 0),
       (8L, 9, u'01', 7733327, 1239), (9L, 10, u'01', 7733755, 1241)], 
      dtype=[('index', '<i8'), ('hru_id_nat', '<i4'), ('region', 'O'), ('POI_ID', '<i4'), ('hru_segment', '<i4')])

但是将其恢复为unicode就像重用原始的datatype对象一样简单。

>>> dt = {'names':('hru_id_nat', 'region', 'POI_ID', 'hru_segment'),
      'formats':('<i4', '<U255', '<i4', '<i4')}
>>> b = a.astype(dt)
>>> b
rec.array([(1, u'01', 7733855, 0), (2, u'01', 7733919, 1244),
       (3, u'01', 7732571, 1236), (4, u'01', 7732387, 1234),
       (5, u'01', 7733327, 1239), (6, u'01', 7733755, 1241),
       (7, u'01', 7732571, 1236), (8, u'01', 7733923, 0),
       (9, u'01', 7733327, 1239), (10, u'01', 7733755, 1241)], 
      dtype=[(u'hru_id_nat', '<i4'), (u'region', '<U255'), (u'POI_ID', '<i4'), (u'hru_segment', '<i4')])

您可能需要小心索引,因此如果不需要,可以在对to_records的调用中包含一个index=False关键字。
1 1.0.0之前的版本,其中引入了StringDType。在Pandas的现代版本中鼓励使用显式类型-参见文本数据类型。

iibxawm4

iibxawm42#

查看文档here
下面是我用来测试它的代码:

import pandas as pd
import numpy as np
arr = pd.DataFrame(data=[(1, u'01', 7733855, 0), (2, u'01', 7733919, 1244),
       (3, u'01', 7732571, 1236), (4, u'01', 7732387, 1234),
       (5, u'01', 7733327, 1239), (6, u'01', 7733755, 1241),
       (7, u'01', 7732571, 1236), (8, u'01', 7733923, 0),
       (9, u'01', 7733327, 1239), (10, u'01', 7733755, 1241)],) 

print arr, '\n', arr.dtypes
arr = arr.astype('string')
arr = arr.astype('int')
print arr.values, '\n', arr.dtypes

输出为

我的版本是python 2.7.6 panda 0.13.1和numpy 1.8.2

bjp0bcyl

bjp0bcyl3#

你可以使用2020年1月Pandas1.0.0中引入的StringDType

import pandas as pd
arr = ([(1, '01', 7733855, 0), (2, '01', 7733919, 1244),
       (3, '01', 7732571, 1236), (4, '01', 7732387, 1234),
       (5, '01', 7733327, 1239), (6, '01', 7733755, 1241),
       (7, '01', 7732571, 1236), (8, '01', 7733923, 0),
       (9, '01', 7733327, 1239), (10, '01', 7733755, 1241)])
df = pd.DataFrame(arr, columns=["hru_id_nat", "region", "POI_ID", "hru_segment"])
df["region"] = df["region"].astype(pd.StringDtype())

现在我们可以使用.str访问器来执行字符串操作:

In [11]: df["region"].str[1]
Out[11]:
0    1
1    1
2    1
3    1
4    1
5    1
6    1
7    1
8    1
9    1
Name: region, dtype: string

请注意,从pandas 1.5.2开始,StringDType()的API仍标记为实验性的,可能会发生更改,因此在生产代码中使用时需自担风险。

相关问题