我有numpy ndarray,它包含两列:一列是日期,例如2011-08-04,另一个是时间,例如19:00:00:081
如何将它们组合成一个datetime对象数组?目前,它们是numpy数组中的字符串。
答案 0 :(得分: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
,你可以用
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
答案 1 :(得分: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()
构建的,因此最好不要加入文本文件中的列并定义合适的转换器(请参阅converters
argument to genfromtxt()
)。
修改:如果评论中指明的列分别为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")
很便宜,因为它不会复制数据。如果您的阵列非常大,那么这种优化可能会受到欢迎,尽管它没有太大的区别。