我的csv文件排列如下:
Person,Date1,Date2,Status
Person1,12/10/11,17/10/11,Done
...
我想对它执行各种操作,我首先将它拉入Python并将日期字符串转换为datetime.datetime对象。我有以下代码:
import re
import numpy as np
from datetime import datetime, timedelta
from dateutil import rrule
def get_data(csv_file = '/home/garry/Desktop/complaints/input.csv'):
inp = np.genfromtxt(csv_file,
delimiter=',',
filling_values = None,
dtype = None)
date = re.compile(r'\d+/\d+/\d+')
count = 0
item_count = 0
for line in inp:
for item in line:
if re.match(date, item):
item = datetime.strptime(item, '%d/%m/%y')
inp[count][item_count] = item
item_count += 1
else:
item_count += 1
item_count = 0
count += 1
return inp
def get_teams(data):
team_list = []
for line in data:
if line[0] not in team_list:
team_list.append(line[0])
else:
pass
del team_list[0]
return team_list
def get_months():
month_list = []
months = [1,2,3,4,5,6,7,8,9,10,11,12]
now = datetime.now()
start_month = now.month - 7
for count in range(0,7):
if months[start_month] > now.month:
year = now.year - 1
else:
year = now.year
month_list.append([months[start_month], year])
start_month += 1
return month_list
if __name__ == "__main__":
inp = get_data()
for item in inp[2]:
print type(item)
team_list = get_teams(inp)
month_list = get_months()
main方法中的print语句(为调试而插入)返回:
<type 'numpy.string_'>
<type 'numpy.string_'>
<type 'numpy.string_'>
<type 'numpy.string_'>
这显然不是我所希望的,因为get_data()函数中的循环应该将日期字符串更改为datetime.datetime对象。当我在各个日期字符串的循环中运行相同的代码作为测试时,他们转换Type就好了。在上面的代码中,它们也在某种意义上工作,因为字符串确实改变为datetime.datetime格式 - 它们不是正确的类型。谁能看到我在这里做错了什么?
答案 0 :(得分:2)
问题是numpy数组的类型是固定的。 Numpy将数据存储在固定大小的连续内存块中,因此当您为numpy
数组中的索引分配值时,numpy
会将其转换为将其存储在数组中。即使使用字符串数组也可以。例如:
>>> a = numpy.array(['xxxxxxxxxx'] * 10)
>>> for index, datum in enumerate(a):
... print datum, a[index], type(a[index])
... a[index] = 5
... print datum, a[index], type(a[index])
...
xxxxxxxxxx xxxxxxxxxx <type 'numpy.string_'>
xxxxxxxxxx 5 <type 'numpy.string_'>
xxxxxxxxxx xxxxxxxxxx <type 'numpy.string_'>
xxxxxxxxxx 5 <type 'numpy.string_'>
xxxxxxxxxx xxxxxxxxxx <type 'numpy.string_'>
xxxxxxxxxx 5 <type 'numpy.string_'>
xxxxxxxxxx xxxxxxxxxx <type 'numpy.string_'>
xxxxxxxxxx 5 <type 'numpy.string_'>
xxxxxxxxxx xxxxxxxxxx <type 'numpy.string_'>
xxxxxxxxxx 5 <type 'numpy.string_'>
xxxxxxxxxx xxxxxxxxxx <type 'numpy.string_'>
xxxxxxxxxx 5 <type 'numpy.string_'>
xxxxxxxxxx xxxxxxxxxx <type 'numpy.string_'>
xxxxxxxxxx 5 <type 'numpy.string_'>
xxxxxxxxxx xxxxxxxxxx <type 'numpy.string_'>
xxxxxxxxxx 5 <type 'numpy.string_'>
xxxxxxxxxx xxxxxxxxxx <type 'numpy.string_'>
xxxxxxxxxx 5 <type 'numpy.string_'>
xxxxxxxxxx xxxxxxxxxx <type 'numpy.string_'>
xxxxxxxxxx 5 <type 'numpy.string_'>
方便(或不!)datetime.datetime
对象可以使用str
转换,所以在这一行...
inp[count][item_count] = item
... numpy
只是将项目转换为字符串并将其插入数组中。
现在,您可以使用dtype=object
来阻止此行为。但这样做会否定numpy
的大部分速度,因为你强迫numpy
调用一堆慢速python代码。
>>> a = numpy.array(['xxxxxxxxxx'] * 10, dtype=object)
>>> for index, datum in enumerate(a):
... print datum, a[index], type(a[index])
... a[index] = 5
... print datum, a[index], type(a[index])
...
xxxxxxxxxx xxxxxxxxxx <type 'str'>
xxxxxxxxxx 5 <type 'int'>
xxxxxxxxxx xxxxxxxxxx <type 'str'>
xxxxxxxxxx 5 <type 'int'>
xxxxxxxxxx xxxxxxxxxx <type 'str'>
xxxxxxxxxx 5 <type 'int'>
xxxxxxxxxx xxxxxxxxxx <type 'str'>
xxxxxxxxxx 5 <type 'int'>
xxxxxxxxxx xxxxxxxxxx <type 'str'>
xxxxxxxxxx 5 <type 'int'>
xxxxxxxxxx xxxxxxxxxx <type 'str'>
xxxxxxxxxx 5 <type 'int'>
xxxxxxxxxx xxxxxxxxxx <type 'str'>
xxxxxxxxxx 5 <type 'int'>
xxxxxxxxxx xxxxxxxxxx <type 'str'>
xxxxxxxxxx 5 <type 'int'>
xxxxxxxxxx xxxxxxxxxx <type 'str'>
xxxxxxxxxx 5 <type 'int'>
xxxxxxxxxx xxxxxxxxxx <type 'str'>
xxxxxxxxxx 5 <type 'int'>
我要补充一点,你并没有充分发挥numpy
的潜力。 Numpy旨在以矢量化方式处理数组,而不使用显式for
循环。 (有关详细信息,请参阅tutorial。)因此,无论何时使用for
循环来处理numpy
,都可以自然地询问如何避免这样做。我会告诉你一件有趣的事情,而不是指出代码中的问题:
>>> numpy.genfromtxt('input.csv', delimiter=',', dtype=None, names=True)
array([('Person1', '12/10/11', '17/10/11', 'Done'),
('Person1', '12/10/11', '17/10/11', 'Done'),
('Person1', '12/10/11', '17/10/11', 'Done'),
('Person1', '12/10/11', '17/10/11', 'Done'),
('Person1', '12/10/11', '17/10/11', 'Done'),
('Person1', '12/10/11', '17/10/11', 'Done')],
dtype=[('Person', '|S7'), ('Date1', '|S8'),
('Date2', '|S8'), ('Status', '|S4')])
>>> a = numpy.genfromtxt('input.csv', delimiter=',', dtype=None, names=True)
>>> a['Status']
array(['Done', 'Done', 'Done', 'Done', 'Done', 'Done'],
dtype='|S4')
>>> a['Date1']
array(['12/10/11', '12/10/11', '12/10/11', '12/10/11', '12/10/11',
'12/10/11'],
dtype='|S8')
现在,您可以直接访问日期,而不是使用正则表达式循环遍历表。
答案 1 :(得分:1)
问题是,您在inp
中定义的get_data
数组会从"|S8
获得np.genfromtxt
dtype。如果您尝试用另一个对象替换其中一个元素,则该对象将转换为字符串。
第一个想法是将inp
转换为包含inp.tolist()
的列表。这样,您可以根据需要更改每个字段的类型。但是有更好的(我认为):
根据您的示例,第二列和第三列始终是日期,对吧?然后,您可以使用datetime
np.genfromtxt
个对象
np.genfromtxt(csv_file,
delimiter=",",
dtype=None,
names=True,
converters={1:lambda d:datetime.strptime(d,"%d/%m/%y"),
2:lambda d:datetime.strptime(d,"%d/%m/%y")})
names=True
表示您将获得结构化ndarray
作为输出,其中的字段取自第一个非注释行(此处为您的Person,Date1,Date2,Status
)。正如您所猜测的那样,converters
关键字会将字符串从第2列和第3列转换为datetime
个对象。
请注意,如果您已经知道您的第一列和最后一列是字符串,那么您可能希望使用另一个dtype
而不是:np.genfromtxt
如果不必猜测类型,则可以更快地运行每一栏。
现在,另一个评论:
for
循环中保留一个计数器,使用for (i, item) in enumerate(whatever)
之类的东西,它更简单。