来自numpy ndarray的日期时间对象的Python数组

时间:2011-09-21 13:48:50

标签: python datetime numpy

我有numpy ndarray,它包含两列:一列是日期,例如2011-08-04,另一个是时间,例如19:00:00:081

如何将它们组合成一个datetime对象数组?目前,它们是numpy数组中的字符串。

2 个答案:

答案 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,你可以用

形成所需的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.txtexample.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() )。

修改:如果评论中指明的列分别为S10S12类型,则可以对此代码进行微小优化,因为您没有需要明确地加入列:

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")很便宜,因为它不会复制数据。如果您的阵列非常大,那么这种优化可能会受到欢迎,尽管它没有太大的区别。