Чистый способ конвертировать квартальные периоды в дату и время в пандах - PullRequest
0 голосов
/ 22 декабря 2018

Я ищу хороший, понятный и понятный способ (тот, который вы можете вспомнить в следующий раз), чтобы преобразовать «Q3 1996» в дату-время панды, например, «1996-07-01» в данном случае.До сих пор я нашел это, но это ужасно некрасиво:

df = pd.DataFrame({'Quarter':['Q3 1996', 'Q4 1996', 'Q1 1997']})
​
df['date'] = (
    pd.to_datetime(
        df['Quarter'].str.split(' ').apply(lambda x: ''.join(x[::-1]))
))
​
print(df)
   Quarter       date
0  Q3 1996 1996-07-01
1  Q4 1996 1996-10-01
2  Q1 1997 1997-01-01

Я надеялся, что следующее будет работать, потому что оно читаемо, но, к сожалению, это не так:

df['date'] = pd.to_datetime(df['Quarter'], format='%q %Y')

Проблематакже этот квартал и год, по-видимому, находятся в неправильном порядке для простой обработки пандами.

Может ли кто-нибудь помочь мне найти более чистый способ преобразования «Q3 1996» в дату-время панд?

Ответы [ 3 ]

0 голосов
/ 22 декабря 2018

Используйте нарезку по последним 4 значениям с первым 2 и преобразуйте в datetime:

df['date'] = pd.to_datetime(df['Quarter'].str[-4:] + df['Quarter'].str[:2])

Строковые операции в пандах медленные, поэтому, если пропущенные значения невозможны, используйте list comprehension:

#python 3.6+ 
df['date'] = pd.to_datetime([f'{x[-4:]}{x[:2]}' for x in df['Quarter']])
#python bellow
#df['date'] = pd.to_datetime(['{}{}'.format(x[-4:], x[:2]) for x in df['Quarter']])
print (df)
   Quarter       date
0  Q3 1996 1996-07-01
1  Q4 1996 1996-10-01
2  Q1 1997 1997-01-01
0 голосов
/ 02 августа 2019

Учитывая формат четверти, такой как 2018-Q1, можно использовать встроенную функцию pd.to_datetime.В качестве общего ответа придется иметь дело с множеством способов хранения наблюдений за квартал (например, 2018:1, 2018:Q1, 20181, Q1:2018 и т. Д.), Приведение данных в формат выше выходит за рамки моего ответа.

Но с учетом отформатированного ряда:

formatted_series = formatted_series_supplier() ...
df['date'] = pd.to_datetime(formatted_series)

И если вы имеете дело с нормативными данными, которые почти всегда отражают конецквартала, а не его начала (т. е. вместо 2019-01-01, вы хотите 2019-03-31), вы можете использовать смещения, как показано ниже:

df['date'] = df['date'] + pd.offsets.QuarterEnd(0)
0 голосов
/ 22 декабря 2018

Вы можете (и должны) использовать pd.PeriodIndex в качестве первого шага, а затем преобразовать в метку времени, используя PeriodIndex.to_timestamp:

qs = df['Quarter'].str.replace(r'(Q\d) (\d+)', r'\2-\1')
qs

0    1996-Q3
1    1996-Q4
2    1997-Q1
Name: Quarter, dtype: object

df['date'] = pd.PeriodIndex(qs, freq='Q').to_timestamp()
df

   Quarter       date
0  Q3 1996 1996-07-01
1  Q4 1996 1996-10-01
2  Q1 1997 1997-01-01

Начальный шаг замены необходим, поскольку PeriodIndex ожидает, что ваши периоды вформат %Y-%q.


Другой вариант - использовать pd.to_datetime после выполнения замены строки таким же образом, как и раньше.

df['date'] = pd.to_datetime(
    df['Quarter'].str.replace(r'(Q\d) (\d+)', r'\2-\1'), errors='coerce')
df

   Quarter       date
0  Q3 1996 1996-07-01
1  Q4 1996 1996-10-01
2  Q1 1997 1997-01-01

Если производительность важна, вы можете разделить и присоединиться, но вы можете сделать это чисто:

df['date'] = pd.to_datetime([
    '-'.join(x.split()[::-1]) for x in df['Quarter']])

df

   Quarter       date
0  Q3 1996 1996-07-01
1  Q4 1996 1996-10-01
2  Q1 1997 1997-01-01
...