[英]how to convert string array of mixed data types
假设我已将文件作为字符串读取并加载到混合数据的2D矩阵中(下面提供了一个示例)
# an example row of the matrix
['529997' '46623448' '2122110124' '2310' '2054' '2' '66' '' '2010/11/03-12:42:08' '26' 'CLEARING' '781' '30' '3' '0' '0' '1']
我想将这块数据转换为它们的数据类型,以便能够使用numpy和scipy对其进行统计分析。
所有列的数据类型都是整数, 除了第8个索引是DateTime,第10个索引是纯字符串。
进行对话的最简单方法是什么?
性能比可读性非常重要,我必须转换450万行数据然后对其进行处理!
这是一个线性的列表理解:
In [24]: from datetime import datetime
In [25]: func = lambda x: datetime.strptime(x, "%Y/%m/%d-%H:%M:%S")
In [26]: [{8:func, 10:str}.get(ind)(item) if ind in {8, 10} else int(item or '0') for ind, item in enumerate(lst)]
Out[26]:
[529997,
46623448,
2122110124,
2310,
2054,
2,
66,
0,
datetime.datetime(2010, 11, 3, 12, 42, 8),
26,
'CLEARING',
781,
30,
3,
0,
0,
1]
我喜欢这样的清晰代码:
from datetime import datetime
input_row = ['529997', '46623448', '2122110124', '2310', '2054',
'2', '66', '', '2010/11/03-12:42:08', '26',
'CLEARING', '781', '30', '3', '0', '0', '1']
_date = lambda x: datetime.strptime(x, "%Y/%m/%d-%H:%M:%S")
# only necessary because '' should be treated as 0
_int = lambda x: int('0' + x)
# specify the type parsers for each column
parsers = 8 * [_int] + [_date, _int, str] + 6 * [_int]
output_row = [parse(input) for parse, input in zip(parsers, input_row)]
根据您的需要,使用迭代器而不是列表。 这样可以大大减少所需的内存量。
我开发了以下函数来转换矩阵的4.5m行,无效数据类型异常也被考虑在内。 尽管可以通过并行化过程来改进它,但是它对我来说确实可以完成,对于它的价值,我将在此发布。
def cnvt_data(mat):
from datetime import datetime
_date = lambda x: datetime.strptime(x, "%Y/%m/%d-%H:%M:%S")
# only necessary because '' should be treated as 0
_int = lambda x: int('0' + x)
# specify the type parsers for each column
parsers = 8 * [_int] + [_date, _int, str] + 6 * [_int]
def try_parse(parse, value, _def):
try:
return parse(value), True
except ValueError:
return _def, False
matrix = [];
for idx in range(len(mat)):
try:
row = mat[idx]
matrix.append(np.asarray([parse(input) for parse, input in zip(parsers, row)]))
except ValueError:
l = [];
matrix.append([])
for _idx, args in enumerate(zip(parsers, row)):
val, pres = try_parse(args[0], args[1], 0)
matrix[-1].append(val)
if(not pres): l.append(_idx);
print "\r[Error] value error @row %d @indices(%s): replaced with 0" %(idx, ', '.join(str(x) for x in l))
print "\r[.] %d%% converted" %(idx * 100/len(mat)),
print "\r[+] 100% converted."
return matrix
通常,当人们要求阅读csv
文件时,我们会要求提供文件样本。 我试图从字符串列表中重建您的行:
In [590]: txt
Out[590]: b'529997, 46623448, 2122110124, 2310, 2054, 2, 66, , 2010/11/03-12:42:08, 26, CLEARING, 781, 30, 3, 0, 0, 1'
( b
表示Py3中的字节串,这是genfromtxt期望其输入的方式)
genfromtxt
需要文件名,打开的文件或任何能为其输入内容的文件。 因此,行列表可以正常工作:
使用dtype=None
可以推导列类型。
In [591]: data=np.genfromtxt([txt], dtype=None, delimiter=',', autostrip=True)
In [592]: data
Out[592]:
array((529997, 46623448, 2122110124, 2310, 2054, 2, 66, False, b'2010/11/03-12:42:08', 26, b'CLEARING', 781, 30, 3, 0, 0, 1),
dtype=[('f0', '<i4'), ('f1', '<i4'), ('f2', '<i4'), ('f3', '<i4'), ('f4', '<i4'), ('f5', '<i4'), ('f6', '<i4'), ('f7', '?'), ('f8', 'S19'), ('f9', '<i4'), ('f10', 'S8'), ('f11', '<i4'), ('f12', '<i4'), ('f13', '<i4'), ('f14', '<i4'), ('f15', '<i4'), ('f16', '<i4')])
结果是一堆int
字段,2个字符串字段。 空白解释为布尔值。
如果我拼出列类型,我得到的数组会稍有不同
In [593]: dt=[int,int,int,int,int,int,int,float,'U20',int, 'U10',int,int,int,int,int,int]
In [594]: data=np.genfromtxt([txt], dtype=dt, delimiter=',', autostrip=True)
In [595]: data
Out[595]:
array((529997, 46623448, 2122110124, 2310, 2054, 2, 66, nan, '2010/11/03-12:42:08', 26, 'CLEARING', 781, 30, 3, 0, 0, 1),
dtype=[('f0', '<i4'), ('f1', '<i4'), ('f2', '<i4'), ('f3', '<i4'), ('f4', '<i4'), ('f5', '<i4'), ('f6', '<i4'), ('f7', '<f8'), ('f8', '<U20'), ('f9', '<i4'), ('f10', '<U10'), ('f11', '<i4'), ('f12', '<i4'), ('f13', '<i4'), ('f14', '<i4'), ('f15', '<i4'), ('f16', '<i4')])
我为空白列指定了float
,然后将其解释为nan
。 黑人的处理可以得到改善。
我将字符串文件更改为unicode(默认py3字符串)。
我应该能够指定日期时间转换,例如到np.datetime64
。
仅用一行, data
就是一个具有复合dtype
的单元素数组0d。
通过名称访问字段
In [598]: data['f8']
Out[598]:
array('2010/11/03-12:42:08',
dtype='<U20')
In [599]: data['f2']
Out[599]: array(2122110124)
速度明智,这可能与您的自定义阅读器相同。 genfromtxt
读取文件并进行解析。 它收集列表中的解析行,并在末尾创建一次数组(我不记得解析行是列表还是dtype数组-我怀疑是列表,但必须学习代码)。
要处理日期,我必须使用'datetime64[s]'
,以及一些如何将日期更改为"2010-11-03T12:42:08"
,可能是在converter
。
===================
我可以根据您的datetime
解析创建一个转换器:
In [649]: from datetime import datetime
In [650]: dateconvert=lambda x: datetime.strptime(x.decode(),"%Y/%m/%d-%H:%M:%S")
In [651]: data=np.genfromtxt([txt], dtype=dt, delimiter=',', autostrip=True, converters={8:dateconvert})
In [652]: data
Out[652]:
array((529997, 46623448, 2122110124, 2310, 2054, 2, 66, nan, datetime.datetime(2010, 11, 3, 12, 42, 8), 26, 'CLEARING', 781, 30, 3, 0, 0, 1),
dtype=[('f0', '<i4'), ('f1', '<i4'), ('f2', '<i4'), ('f3', '<i4'), ('f4', '<i4'), ('f5', '<i4'), ('f6', '<i4'), ('f7', '<f8'), ('f8', '<M8[s]'), ('f9', '<i4'), ('f10', '<U10'), ('f11', '<i4'), ('f12', '<i4'), ('f13', '<i4'), ('f14', '<i4'), ('f15', '<i4'), ('f16', '<i4')])
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.