拆分时间戳列CSV

时间:2016-10-03 20:48:21

标签: python csv numpy delimited-text

我有以下格式的CSV文件:

name, lat, lon, alt, time
id1, 40.436047, -74.814883, 33000, 2016-01-21T08:08:00Z

我正在尝试使用Python将时间分成新列,所以它看起来像这样:

name, lat, lon, alt, year, month, day, hour, min, sec
id1, 40.436047, -74.814883, 33000, 2016,-01,-21, 08, 08, 00

我还想将浮点列中的位数设置为始终设置为5位小数。

这是我到目前为止的脚本:

import numpy as np

name,lat,lon,alt,time = np.loadtxt(
    'test_track.csv',
    delimiter=',',
    dtype='str',
    skiprows=1,
    unpack = True
    )


year = time[0:3]
print year

不幸的是,它没有将时间解析为年份,而是打印出第一个完整时间而不是仅仅是一年。

3 个答案:

答案 0 :(得分:2)

[编辑+实际上这次在我的电脑上运行了..]

与其他提到的一样,我认为使用内置库来做你想做的事就足够了。使用dateutil解析器应该允许您以简单的方式使用datetime列。

但是如果您仍想重新创建CSV文件......

要以您希望的格式创建新的CSV文件,您可以执行以下操作:

#!/usr/bin/env python

import dateutil.parser
import csv

with open('original.csv', 'rb') as csvfile:
    reader = csv.reader(csvfile, delimiter=',')

    write_file = open("new.csv", 'w')

    reading_label_line = True

    for row in reader:
        if reading_label_line:
            reading_label_line = False
            write_file.write("name, lat, lon, alt, year, month, day, hour, min, sec\n")
        else:
            dt = dateutil.parser.parse(row[-1])
            row = row[0:len(row)-1] # cut off the last item (datetime)
            row.append(dt.year)
            row.append(dt.month)
            row.append(dt.day)
            row.append(dt.hour)
            row.append(dt.minute)
            row.append(dt.second)
            write_file.write(', '.join(str(x) for x in row) + '\n')

如果你想保留' - '在月和日前,只需在dt.month和dt.day之前添加短划线。

答案 1 :(得分:0)

您应该尝试使用Pandas而不是numpy导入数据。 Panda read_csv很好地处理日期

尝试这样的事情

import pandas as pd
yourData = pd.read_csv(yourData_Path,delimiter = ',',skiprows = 0,
           parse_dates={'time':[-1]},header = 1,na_values = -9999)

Pandas还允许您按日期时间进行索引,这非常好:)

答案 2 :(得分:0)

这个答案跟随您使用loadtxt的主角,希望能够解释您所获得的内容以及替代方案。但是,如果您没有进行任何计算,那么只需读取每一行,拆分它并以所需格式将其写回来可能更简单。 csv读者可以使该任务更简单,但不是必需的。纯Python行读写,字符串操作都可以。

============

使用样本的字符串副本(PY3中的字节字符串):

In [296]: txt=b"""name, lat, lon, alt, time
     ...: id1, 40.436047, -74.814883, 33000, 2016-01-21T08:08:00Z
     ...: id2, 40.436047, -74.814883, 33000, 2016-01-21T08:08:00Z""".splitlines(
     ...: )
In [297]: txt
Out[297]: 
[b'name, lat, lon, alt, time',
 b'id1, 40.436047, -74.814883, 33000, 2016-01-21T08:08:00Z',
 b'id2, 40.436047, -74.814883, 33000, 2016-01-21T08:08:00Z']

In [298]: data=np.loadtxt(txt,delimiter=',',dtype=np.string_,skiprows=1)
In [299]: data
Out[299]: 
array([[b'id1', b' 40.436047', b' -74.814883', b' 33000',
        b' 2016-01-21T08:08:00Z'],
       [b'id2', b' 40.436047', b' -74.814883', b' 33000',
        b' 2016-01-21T08:08:00Z']], 
      dtype='|S21')
In [300]: data[:,4]
Out[300]: 
array([b' 2016-01-21T08:08:00Z', b' 2016-01-21T08:08:00Z'], 
      dtype='|S21')

或者解压缩

In [302]: name,lat,lon,alt,time=np.loadtxt(txt,delimiter=',',dtype=np.string_,sk
     ...: iprows=1,unpack=True)
In [303]: time
Out[303]: 
array([b' 2016-01-21T08:08:00Z', b' 2016-01-21T08:08:00Z'], 
      dtype='|S21')

我们已将文件加载为2d字符串数组或5个1d数组。 time是一个字符串数组。

我可以将这个字符串数组转换为数据时对象数组:

In [307]: time1 = time.astype(np.datetime64)
In [308]: time1
Out[308]: array(['2016-01-21T08:08:00', '2016-01-21T08:08:00'], dtype='datetime64[s]')
In [309]: time1[0]
Out[309]: numpy.datetime64('2016-01-21T08:08:00')

我甚至可以用日期时间直接加载它。但这并不能解决您的显示问题。

=====================

genfromtxt为加载不同的列类型提供了更多的力量

In [312]: np.genfromtxt(txt,dtype=None,skip_header=1,delimiter=',')
Out[312]: 
array([(b'id1', 40.436047, -74.814883, 33000, b' 2016-01-21T08:08:00Z'),
       (b'id2', 40.436047, -74.814883, 33000, b' 2016-01-21T08:08:00Z')], 
      dtype=[('f0', 'S3'), ('f1', '<f8'), ('f2', '<f8'), ('f3', '<i4'), ('f4', 'S21')])

这给出了字符串,浮点数和int的混合。日期仍然是字符串。

如果我用特定的dtype替换dtype=None,我可以像以前一样约会:

In [313]: dt=['S3','f','f','i','datetime64[s]']

In [315]: data=np.genfromtxt(txt,dtype=dt,skip_header=1,delimiter=',')

In [316]: data
Out[316]: 
array([ (b'id1', 40.4360466003418, -74.81488037109375, 33000, datetime.datetime(2016, 1, 21, 8, 8)),
       (b'id2', 40.4360466003418, -74.81488037109375, 33000, datetime.datetime(2016, 1, 21, 8, 8))], 
      dtype=[('f0', 'S3'), ('f1', '<f4'), ('f2', '<f4'), ('f3', '<i4'), ('f4', '<M8[s]')])
In [317]: data['f4']
Out[317]: array(['2016-01-21T08:08:00', '2016-01-21T08:08:00'], dtype='datetime64[s]')

===============

第一次将此写回文件

In [318]: np.savetxt('test.txt',data,fmt='%4s, %.5f, %.5f, %d, %s')

In [320]: cat test.txt
b'id1', 40.43605, -74.81488, 33000, 2016-01-21T08:08:00
b'id2', 40.43605, -74.81488, 33000, 2016-01-21T08:08:00

控制浮动精度是显而易见的。我需要修复第一个字节的字符串显示。并且它没有分割日期 - 我只是显示正常的字符串表示。

=================

您可以将np.datetime64数组转换为datetime个对象数组:

In [361]: from datetime import datetime
In [362]: data['f4'].astype(datetime)
Out[362]: 
array([datetime.datetime(2016, 1, 21, 8, 8),
       datetime.datetime(2016, 1, 21, 8, 8)], dtype=object)

我可以使用逗号分隔符将其转换为字符串数组:

In [383]: tfmt='%Y, %m, %d, %H, %M, %S'
In [384]: timefld=data['f4'].astype(datetime)
In [385]: timefld = np.array([d.strftime(tfmt) for d in timefld])
In [386]: timefld
Out[386]: 
array(['2016, 01, 21, 08, 08, 00', '2016, 01, 21, 08, 08, 00'], 
      dtype='<U24')

=========================

纯文本编辑方法可以使用

之类的功能
def foo(dtstr):
    return dtstr.replace(b'-',b', ').replace(b':',b', ').replace(b'T',b', ').replace(b'Z',b'')

def foo(dtstr):
    # cleaner version with re
    import re
    return re.sub(b'[-:T]',b', ',dtstr[:-1])


def editline(aline):
    aline=aline.split(b',')
    aline[4]=foo(aline[4])
    return b', '.join(aline)

In [408]: [editline(aline) for aline in txt[1:]]
Out[408]: 
[b'id1,  40.436047,  -74.814883,  33000,  2016, 01, 21, 08, 08, 00',
 b'id2,  40.436047,  -74.814883,  33000,  2016, 01, 21, 08, 08, 00']