Почему datetime.strptime не работает с numpy, в котором аргумент 'float () должен быть строкой или числом, а не datetime.datetime' - PullRequest
0 голосов
/ 07 апреля 2020

Я пытаюсь получить тип datetime для использования в массиве numpy (datep) здесь. Я попытался подходит для функции bytespdates2num.

Первый:

    def bytespdates2num(fmt,encoding = 'utf-8'):
        def bytesconverter(b):
            s = b.decode(encoding)
            return mdate.datestr2num(s)
        return bytesconverter

Второй:

    def bytespdates2num(fmt, encoding = 'utf-8'):
        def bytesconverter(b):
            s = b.decode(encoding)
            return datetime.datetime.strptime(s)
        return bytesconverter

Мой код:

import urllib
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import numpy as np
import ssl
import requests
import json
import datetime

#First or second approach
def bytespdates2num(fmt, encoding = 'utf-8'):
     def bytesconverter(b):
         #makes it into string from utf-8 encoding format
        s  = b.decode(encoding)
        return datetime.datetime.strptime(s,fmt)
     return bytesconverter

url1 = 'https://pythonprogramming.net/yahoo_finance_replacement'
data = urllib.request.urlopen(url1,context = None).read().decode()
stockprices = list()
stocksplitdata = data.split('\n')
for line in stocksplitdata:
    stockprices.append(line)

date,openp,highp,lowp,closep,adjust,vol = np.loadtxt(stockprices[1:],delimiter = ',',\
                                                     unpack = True,\
                                                     converters = {0:bytespdates2num('%Y-%m-%d')})

Пока работает первый подход и я можно приступить к построению графика matplotlib, используя datep в качестве оси, второй подход не дает float() argument must be a string or a number, not 'datetime.datetime. Однако при отладке при запуске строки datetime.datetime.strptime(s) в командной строке объект datetime получает значение s. Почему это происходит? Подход datetime также превращает строковый формат даты в формат даты и времени, и кажется более простым.

1 Ответ

2 голосов
/ 07 апреля 2020

Даже если вы указываете конвертер, вам все равно нужно указать dtype.

Я пытался воссоздать ваш случай с помощью простого ввода (ПОЧЕМУ ВЫ ЭТО НЕ ДЕЛАЕТЕ ДЛЯ НАС ???)

In [20]: txt = """2011-01-23 
    ...: 2020-03-23"""

Ваш второй конвертер (один из ваших пропускает fmt):

In [21]: def bytespdates2num(fmt, encoding = 'utf-8'): 
    ...:         def bytesconverter(b): 
    ...:             s = b.decode(encoding) 
    ...:             return datetime.datetime.strptime(s, fmt) 
    ...:         return bytesconverter 
    ...:                                                                                       

Ваш бег с ПОЛНОЙ TRACEBACK!

In [22]: np.loadtxt(txt.splitlines(), converters={0:bytespdates2num('%Y-%m-%d')})              
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-22-56c1854d614f> in <module>
----> 1 np.loadtxt(txt.splitlines(), converters={0:bytespdates2num('%Y-%m-%d')})

/usr/local/lib/python3.6/dist-packages/numpy/lib/npyio.py in loadtxt(fname, dtype, comments, delimiter, converters, skiprows, usecols, unpack, ndmin, encoding, max_rows)
   1159         for x in read_data(_loadtxt_chunksize):
   1160             if X is None:
-> 1161                 X = np.array(x, dtype)
   1162             else:
   1163                 nshape = list(X.shape)

TypeError: float() argument must be a string or a number, not 'datetime.datetime'

The по умолчанию dtype для loadtxt - это число с плавающей запятой. Он имеет read_data (в виде списка списков) и теперь пытается преобразовать его в массив, используя значение по умолчанию dtype.

Если вместо этого я задаю object в качестве dtype:

In [23]: np.loadtxt(txt.splitlines(), converters={0:bytespdates2num('%Y-%m-%d')}, dtype=object)
    ...:                                                                                       
Out[23]: 
array([datetime.datetime(2011, 1, 23, 0, 0),
       datetime.datetime(2020, 3, 23, 0, 0)], dtype=object)

Или я мог бы указать datetime64 dtype:

In [24]: np.loadtxt(txt.splitlines(), converters={0:bytespdates2num('%Y-%m-%d')}, dtype='datetime64[D]')                                                                             
Out[24]: array(['2011-01-23', '2020-03-23'], dtype='datetime64[D]')

Извините за заглавные буквы, но я устал просить трассировки и примеры вводимых данных. Их предоставление должно быть обязательным для вопросов SO.

С mdates (без исправления в коде):

In [30]:     def bytespdates2num(fmt,encoding = 'utf-8'): 
    ...:         def bytesconverter(b): 
    ...:             s = b.decode(encoding) 
    ...:             return mdates.datestr2num(s) 
    ...:         return bytesconverter 
    ...:                                                                                       
In [31]: np.loadtxt(txt.splitlines(), converters={0:bytespdates2num('%Y-%m-%d')})              
Out[31]: array([734160., 737507.])

Очевидно, это возвращает число, а не объект времени данных.

...