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

abu*_*dis 3 python datetime numpy

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

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

unu*_*tbu 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)
Run Code Online (Sandbox Code Playgroud)

鉴于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
Run Code Online (Sandbox Code Playgroud)

在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')
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)