从numpy ndarray创建Python的datetime对象数组
我有一个numpy的ndarray,它里面有两列:一列是日期,比如2011-08-04,另一列是时间,比如19:00:00:081。
我该怎么把它们合并成一个包含日期时间对象的数组呢?现在它们在numpy数组里都是字符串形式。
2 个回答
2
要回答这个问题,如果你有一个两列的NumPy数组 a
,你可以这样做:
b = numpy.array([datetime.datetime.strptime(s + t, "%Y-%m-%d%H:%M:%S:%f")
for s, t in a])
因为评论里提到原始数组 a
是用 genfromtxt()
创建的,所以你可能更好地在文本文件中把列合并起来,并定义一个合适的转换器(可以参考genfromtxt()
的 converters
参数)。
编辑:如果这两列的类型分别是 S10
和 S12
,那么你可以稍微优化一下这个代码,因为你不需要明确地合并这两列:
a = numpy.array([("2011-08-04", "19:00:00:081"),
("2011-08-04", "19:00:00:181")],
dtype=[("", "S10"), ("", "S12")])
b = numpy.array([datetime.datetime.strptime(s, "%Y-%m-%d%H:%M:%S:%f")
for s in a.view("S22")])
操作 a.view("S22")
是很简单的,因为它并不会复制数据。如果你的数组真的很大,这个优化可能会很有用,尽管它的影响不是特别大。
8
如果在example.txt这个数据文件中,日期和时间的字符串是放在一列里,没有空格分隔,那么可以用genfromtxt
把它转换成日期时间对象,像这样:
import numpy as np
import datetime as dt
def mkdate(text):
return dt.datetime.strptime(text, '%Y-%m-%dT%H:%M:%S:%f')
data = np.genfromtxt(
'example.txt',
names=('data','num','date')+tuple('col{i}'.format(i=i) for i in range(19)),
converters={'date':mkdate},
dtype=None)
如果直接使用example.txt
,你可以这样形成想要的numpy数组:
import numpy as np
import datetime as dt
import csv
def mkdate(text):
return dt.datetime.strptime(text, '%Y-%m-%d%H:%M:%S:%f')
def using_csv(fname):
desc=([('data', '|S4'), ('num', '<i4'), ('date', '|O4')]+
[('col{i}'.format(i=i), '<f8') for i in range(19)])
with open(fname,'r') as f:
reader=csv.reader(f,delimiter='\t')
data=np.array([tuple(row[:2]+[mkdate(''.join(row[2:4]))]+row[4:])
for row in reader],
dtype=desc)
# print(mc.report_memory())
return data
在numpy数组中合并两列可能会比较慢,特别是当数组很大的时候。这是因为合并操作就像调整大小一样,需要为新的数组分配内存,并把原数组的数据复制到新数组中。所以我觉得直接形成正确的numpy数组是值得尝试的,而不是分步骤进行(先形成一个部分正确的数组,再合并两列)。
顺便说一下,我测试过上面的csv
代码和合并两列的速度(下面的)。从csv
形成一个单一数组的速度更快(而且内存使用差不多):
import matplotlib.cbook as mc
import numpy as np
import datetime as dt
def using_genfromtxt(fname):
data = np.genfromtxt(fname, dtype=None)
orig_desc=data.dtype.descr
view_desc=orig_desc[:2]+[('date','|S22')]+orig_desc[4:]
new_desc=orig_desc[:2]+[('date','|O4')]+orig_desc[4:]
newdata = np.empty(data.shape, dtype=new_desc)
fields=data.dtype.names
fields=fields[:2]+fields[4:]
for field in fields:
newdata[field] = data[field]
newdata['date']=np.vectorize(mkdate)(data.view(view_desc)['date'])
# print(mc.report_memory())
return newdata
# using_csv('example4096.txt')
# using_genfromtxt('example4096.txt')
example4096.txt
和example.txt
是一样的,只是重复了4096次。它大约有12K行。
% python -mtimeit -s'import test' 'test.using_genfromtxt("example4096.txt")'
10 loops, best of 3: 1.92 sec per loop
% python -mtimeit -s'import test' 'test.using_csv("example4096.txt")'
10 loops, best of 3: 982 msec per loop