python - 为什么以下对象是 numpy 字符串而不是 datetime.datetime 对象?

标签 python date csv numpy

我有一个 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()

主方法中的打印语句(插入用于调试)返回:

<type 'numpy.string_'>
<type 'numpy.string_'>
<type 'numpy.string_'>
<type 'numpy.string_'>

这显然不是我所希望的,因为 get_data() 函数中的循环应该将日期字符串更改为 datetime.datetime 对象。当我在单个日期字符串的循环中运行相同的代码作为测试时,它们可以很好地转换类型。在上面的代码中,它们在某种意义上也起作用,因为字符串确实更改为 datetime.datetime 格式 - 它们只是不是正确的类型。谁能看到我在这里做错了什么吗?

最佳答案

问题在于 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')

现在,您可以直接访问日期,而无需使用正则表达式循环遍历表格。

关于python - 为什么以下对象是 numpy 字符串而不是 datetime.datetime 对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12028638/

相关文章:

java - 从Java中的List在neo4j数据库中创建大量节点

python - Numba 支持 cuda 协作 block 同步?? Python numba cuda 网格同步

python - 为什么我的字体在 tkinter 中无法正确显示?

java - 斯卡拉/Java : Ignore DateTimeException

r - 按时间间隔创建每月平均值

java - 从特定的 CSV 文件中读取数据并将其显示在 JTable 中

python - 使用 aiohttp 在 Python 中从内存上传 multipart/form-data

python - 使用Python读取csv时指定换行符 ('\n' )

java - 为什么 setLastModified(time) 不适用于此文件?

java - 使用 Java 验证 CSV 文件