在Numpy中导出ISO日期

1 投票
2 回答
2282 浏览
提问于 2025-04-17 05:29

我刚开始学习Python,有个基本的问题在网上找不到解决办法。

我有一个名为IBTsample.txt的表格,内容如下:

  • 季节, ISO时间, 纬度, 经度, 枚举
  • 2009, 2009-12-24 12:00:00, 6.50, 85.00, 2
  • 2009, 2009-12-25 06:00:00, 8.00, 84.50, 6
  • 2009, 2009-12-25 00:00:00, 7.00, 84.50, 4
  • 2009, 2009-12-24 18:00:00, 6.50, 85.00, 3
  • 2009, 2009-12-24 09:00:00, 6.50, 85.00, 1
  • 2009, 2009-12-25 03:00:00, 7.00, 84.50, 5

我想做的是把它导入为一个numpy数组,进行一些处理(目前只是按日期对记录进行排序),然后把处理后的表格导出到一个新的.txt文件中。

from numpy import *
import pylab

rawtable = loadtxt('IBTsample.txt', delimiter=',', skiprows=1, converters=    {1:pylab.datestr2num},\
               dtype={'names':('Season','ISO_time','Latitude','Longitude','Enum'),\
                      'formats':('uint16','float','float16','float16','uint8')})
sortable = (sort(rawtable, order=('ISO_time'))).copy()
savetxt('IBTsorted.txt', sortable, fmt='%d,%.3f,%.1f,%.1f,%d')

在导入时我需要使用pylab.datestr2num函数,但找不到一个反向函数来把日期和时间导出为ISO格式。

任何帮助或想法都会很有用。

2 个回答

1

除了@unutbu的回答,如果你使用的是最新版本的numpy(>= 1.7),它有一个原生的日期数据类型。

在这种情况下,可以试试下面的代码:

import numpy as np
import dateutil.parser

rawtable = np.genfromtxt('test_in.txt', names=True, delimiter=',', 
                converters={1:dateutil.parser.parse},
                dtype=[np.uint16, np.datetime64, np.float, np.float, np.uint8])

sorttable = np.sort(rawtable, order=('ISO_time'))

with open('test_out.txt', 'w') as outfile:
    outfile.write(','.join(sorttable.dtype.names) + '\n')
    np.savetxt(outfile, sorttable, fmt='%i,%r,%f,%f,%i')

这样会得到:

Season,ISO_time,Latitude,Longitude,Enum
2009,2009-12-24 09:00:00,6.500000,85.000000,1
2009,2009-12-24 12:00:00,6.500000,85.000000,2
2009,2009-12-24 18:00:00,6.500000,85.000000,3
2009,2009-12-25 00:00:00,7.000000,84.500000,4
2009,2009-12-25 03:00:00,7.000000,84.500000,5
2009,2009-12-25 06:00:00,8.000000,84.500000,6
3

你可以使用 matplotlib.dates.num2date 这个功能,把数字转换回日期时间对象。然后再调用 isoformat(),这样就能把日期以 ISO-8601 格式的字符串形式输出。

import numpy as np
import matplotlib.dates as md

def num2isodate(num):
    result=md.num2date(num).isoformat()
    return result

rawtable = np.loadtxt(
    'IBTsample.txt', delimiter=',', skiprows=1,
    converters= {1:md.datestr2num},
    dtype={'names':['Season','ISO_time','Latitude','Longitude','Enum'],
           'formats':['uint16','float','f4','f4','uint8']})

ISO_time 的数据类型转换成 object。这样这个列就可以先存放浮点数,后面再存放字符串。需要注意的是,下面的 astype 会返回一个副本,所以不需要再显式调用 copy 了。而且,因为你已经调用了 copy,我假设在内存中保留两个数组副本不是问题。(如果内存紧张,我们可以用 csv 模块逐行写入数组,而不是用 np.savetxt。但因为内存不是问题,使用 np.savetxt 更方便。)

sortable = rawtable.astype({'names':['Season','ISO_time','Latitude','Longitude','Enum'],
                            'formats':['uint16','object','f4','f4','uint8']})
sortable = np.sort(sortable, order=('ISO_time'))
sortable['ISO_time'] = [num2isodate(num) for num in sortable['ISO_time']]
np.savetxt('IBTsorted.txt', sortable, fmt='%d,%s,%.1f,%.1f,%d')

顺便说一句,我建议不要使用 from module import *,特别是当 modulenumpy 的时候。这会覆盖一些 Python 内置的功能,比如 absallanyminmaxsumround 等等。这样不仅让调用 Python 内置功能变得困难,还容易写出看起来没问题但实际上有难以发现或微妙错误的代码。

撰写回答