читать csv в индексе года, дня года и часа/минуты в объект даты и времени pandas

Я пытаюсь прочитать в csv в этой форме:

2014,92,1931,6.234,10.14
2014,92,1932,5.823,9.49
2014,92,1933,5.33,7.65
2014,92,1934,4.751,6.19
2014,92,1935,4.156,5.285
2014,92,1936,3.962,4.652
2014,92,1937,3.74,4.314
2014,92,1938,3.325,3.98
2014,92,1939,2.909,3.847
2014,92,1940,2.878,3.164

Чтобы было ясно, это (год, день года, время 24:00 и 2 столбца значений).

У меня были некоторые мысли по этому поводу в предыдущем вопросе, но безрезультатно, и это оказалось вопросом нескольких проблем... (Создать индексированную дату и время из информации о дате/времени в 3 столбцах с помощью pandas)

Как отмечено в предыдущем вопросе, следующая попытка "read_csv"

df = pd.read_csv("home_prepped.dat", parse_dates={"dt" : [0,1,2]}, 
                  date_parser=parser, header=None)

вызывает TypeError:

TypeError: parser() takes exactly 1 argument (3 given) 

Это связано с тем, что аргумент "parse_dates" содержит 0,1,2. Я также попытался поместить их в двойные скобки [[0,1,2]] и получить:

ValueError: [0, 1, 2] is not in list

Я преодолел это, установив parse_dates=True, и подумал, что могу просто установить set_index после, но получить это:

TypeError: должна быть строка, а не numpy.int64

Мой синтаксический анализатор тоже зацикливается на формате, и я читал противоречивые истории о заполнении нулями значения «день года». Мои не заполнены нулями, но даже несмотря на вышеперечисленные ошибки, у меня был формат, зависший от первого значения, года! Вот парсер:

def parser(x):
    return pd.datetime.strptime(x, '%Y %j %H%M')

Так что да, у меня были ошибки, говорящие о том, что «2014» не распознан, а «92» (день года) не распознан, но это было поощрено, потому что, по крайней мере, strptime смог пройти «сквозь», чтобы опробовать формат.

Мне интересно, имеет ли это какое-то отношение к моим данным.

Я ищу способ получить эту информацию о дате и времени, проиндексированную как дату и время, и у меня не было ничего, кроме проблем. Я пошел дальше и дополнил некоторые джулианы на случай, если кто-то захочет проверить, что формат является проблемой заполнения, см. ниже:

2014,092,1931,6.234,10.14
2014,092,1932,5.823,9.49
2014,092,1933,5.33,7.65
2014,092,1934,4.751,6.19
2014,092,1935,4.156,5.285
2014,092,1936,3.962,4.652
2014,092,1937,3.74,4.314
2014,092,1938,3.325,3.98
2014,092,1939,2.909,3.847
2014,092,1940,2.878,3.164

Спасибо за вашу помощь, ребята, я начинаю действительно разочаровываться здесь: S


person geokrowding    schedule 28.12.2014    source источник


Ответы (2)


После исправления вашего %m (месяца) до %M (минуты) ваш код работает для меня:

>>> import pandas as pd
>>> print pd.version.version
0.15.2-10-gf7af818
>>> 
>>> def parser(x):
...         return pd.datetime.strptime(x, '%Y %j %H%M')
... 
>>> df = pd.read_csv("home_prepped.dat", parse_dates={"dt" : [0,1,2]}, 
...                  date_parser=parser, header=None)
>>> df
                   dt      3       4
0 2014-04-02 19:31:00  6.234  10.140
1 2014-04-02 19:32:00  5.823   9.490
2 2014-04-02 19:33:00  5.330   7.650
3 2014-04-02 19:34:00  4.751   6.190
4 2014-04-02 19:35:00  4.156   5.285
5 2014-04-02 19:36:00  3.962   4.652
6 2014-04-02 19:37:00  3.740   4.314
7 2014-04-02 19:38:00  3.325   3.980
8 2014-04-02 19:39:00  2.909   3.847
9 2014-04-02 19:40:00  2.878   3.164

Но после того, как я немного поиграл с этим, обнаружилось очень странное поведение при возникновении ошибки, приводящее к некоторым странным сообщениям об ошибках, поэтому я понимаю, почему это очень сложно отлаживать.


Если по какой-то причине вышеуказанное не работает, вы можете попробовать выполнить синтаксический анализ самостоятельно:

df = pd.read_csv("home_prepped.dat", header=None)
timestr = df.iloc[:,:3].astype(str).apply(' '.join,axis=1)
df = df.iloc[:,3:]
times = pd.to_datetime(timestr, format='%Y %j %H%M')
df["dt"] = times

Как упоминалось выше, когда что-то идет не так (например, ошибка синтаксического анализа), сообщения об ошибках изнутри read_csv очень сбивают с толку.

person DSM    schedule 28.12.2014
comment
о да, ежемесячная опечатка, спасибо; Я это увидел сразу после поста. В любом случае, я ценю работу над этим... Я должен был упомянуть, что я использую версию: In [80]: pd.__version__ Out [80]: '0.15.2' - person geokrowding; 28.12.2014
comment
Я отредактировал, чтобы включить очень грубый способ сделать это. Если с вашими данными что-то не так, что вызывает проблему, строка times может не работать. Если это так, то вам просто нужно найти проблемные значения. - person DSM; 28.12.2014
comment
Эй, это здорово, ты действительно знаешь свое дело. Я больше знаком с bash, чем с python. Как вы думаете, мне было бы проще, если бы я конвертировал даты, прежде чем превращать их в панд? - person geokrowding; 28.12.2014
comment
возможно, это %j, который возится с ним, поскольку это не совсем юлианский день, а скорее день года. - person geokrowding; 28.12.2014
comment
У меня возникла идея: как вы думаете, я должен просто вручную создать диапазон дат, а затем добавить значения в диапазон? Если это так, я полагаю, мне придется беспокоиться о переходе на летнее время и других сдвигах - person geokrowding; 28.12.2014
comment
Вам решать. Если вы загрузите файл на один из временных сайтов, таких как dpaste, я могу посмотреть, но пока не возникли проблемы с анализом того, что вы показали, предполагая, что проблема находится позже в файле. Вы можете выполнять ручную работу в bash, но если что-то вызывает проблемы для pandas, это, вероятно, вызовет проблемы и для других алгоритмов, но молча. - person DSM; 28.12.2014

Я думаю, что следующее работает. Имейте в виду, что это первый раз, когда я когда-либо приносил что-либо в pandas для работы, поэтому не знаю, как правильно его протестировать, но он распознает формат и говорит:

<class 'pandas.tseries.index.DatetimeIndex'>
[2014-04-02 19:31:00, ..., 2014-12-21 23:59:00]
Length: 337917, Freq: None, Timezone: None

Что мило, поскольку я считаю, что это означает, что я, наконец, проиндексировал дату и время!

Вот что я сделал...

In [41]:

import numpy as np
import pandas as pd
from datetime import datetime
In [60]:

def parse(yr, yearday, hrmn):
          date_string = ''.join([yr, yearday, hrmn])
          return datetime.strptime(date_string,"%Y%j%H%M")
In [61]:


df = pd.read_csv('home_prepped.csv', parse_dates={'datetime':[0,1,2]}, date_parser=parse, index_col='datetime', header=None)

Теперь я попытался поставить пробел между '' перед .join, и он разделил %Y %j, но смог увидеть только «1» как часть %H. Поэтому я избавился от пробела и изменил формат, чтобы он тоже был без пробелов.

Спасибо за вашу работу над этим DSM.

person geokrowding    schedule 28.12.2014