在Numpy 1.6.1中将float32数组转换为datetime64

8
什么是在numpy中将整数日期转换为datetime64的正确方法?我尝试过以下代码:
import numpy
a = numpy.array([20090913, 20101020, 20110125])
numpy.datetime64(a.astype("S8"))

但是可能会出现错误的转换。使用numpy.loadtxt正确地将它们读取为numpy.datetime64对象(它们来自于csv文件)如何呢?

2个回答

5
你遇到的问题是 datetime64 需要一个符合格式 yyyy-mm-dd 的字符串,而类型转换生成的字符串格式为 yyyymmdd。我建议您尝试如下解决方案:
conversion = lambda x: "%s-%s-%s" % (x[:4], x[4:6], x[6:])
np_conversion = numpy.frompyfunc(conversion,1,1)
b = np_conversion(a.astype('S10'))
numpy.datetime64(b)

然而,对于我来说(我使用的是numpy 1.6.1),它并没有起作用,出现了“NotImplementedError: Not implemented for this type”这个错误信息。除非在1.7版本中有所改进,否则我只能建议使用纯Python解决方案:

numpy.datetime64(numpy.array([conversion(str(x)) for x in a], dtype="S10"))

为了以期望的格式提供日期,您需要进行输入的转换或预处理。

编辑:我还可以提供一种替代方案,使用vectorize,但是我不太清楚它的工作原理,所以我不知道哪里出了问题:

>>> conversion = vectorize(lambda x: "%s-%s-%s" % (x[:4], x[4:6], x[6:]), otypes=['S10'])
>>> conversion(a.astype('S10'))
array(['2009', '2010', '2011'],
      dtype='|S4')

由于某种原因,它忽略了“otypes”并输出“|S4”而不是“|S10”。很抱歉我不能提供更多帮助,但这应该为搜索其他解决方案提供了一个起点。
更新:感谢OP的反馈,我想到了一个新的可能性。这应该会按预期工作:
>>> conversion = lambda x: numpy.datetime64(str(x))
>>> np_conversion = numpy.frompyfunc(conversion, 1, 1)
>>> np_conversion(a)
array([2009-09-13 00:00:00, 2010-10-20 00:00:00, 2011-01-25 00:00:00], dtype=object)

# Works too:
>>> conversion = lambda x: numpy.datetime64("%s-%s-%s" % (x/10000, x/100%100, x%100))

很奇怪,在这种情况下,datetime64带或不带破折号都可以正常工作...


+1,你的第一个解决方案对我来说似乎完全可行(NumPy 2.0 dev)。 - doug
我想知道为什么numpy.datetime64('20090921')可以工作,因为所需的格式是带破折号的? - Benjamin
@Benjamin 真的很奇怪...但是你的评论给了我一个新的想法,试试我的更新答案,对我来说效果很好。 - mgibsonbr
基本上,numpy.array([numpy.datetime64(str(i)) for i in a])。不过我在想是否有比这更直接的方法。 - Benjamin
@Benjamin:更直接的方式是什么意思?是指直接从CSV/文本文件中读取数据吗? - joris
我的意思是进行类型转换不应该需要使用列表推导式,一定有更好的方法。 - Benjamin

5

奇怪的是,这个方法可行:numpy.datetime64(a.astype("S8").tolist()),而这个方法不行:numpy.datetime64(a.astype("S8"))。第一种方法仍然比较简单,不像这个方法:numpy.array([numpy.datetime64(str(i)) for i in a])。我在这个问题中询问了原因。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接