在 pandas 中将季度期间转换为日期时间的简洁方法
Clean way to convert quarterly periods to datetime in pandas
编辑:
如果您要回答这个问题并且您的字符串看起来像 1996-Q1
,那么只需使用 pd.to_datetime(df['Quarter'])
将其转换为正确的 pandas 日期时间。这道题是要解决所有不是这个标准格式的季度日期。
原问题:
我正在寻找一种将 Q3 1996
转换为 pandas 日期时间(例如本例中的 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')
问题还在于季度和年份的顺序显然是错误的 pandas 无法进行简单处理。
谁能帮我找到一种更简洁的方法将 Q3 1996
转换为 pandas 日期时间?
您可以(并且应该)使用 pd.PeriodIndex
作为第一步,然后使用 PeriodIndex.to_timestamp
:
转换为时间戳
qs = df['Quarter'].str.replace(r'(Q\d) (\d+)', r'-')
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'-'), 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
使用前 4 个值切片 2
并转换为日期时间:
df['date'] = pd.to_datetime(df['Quarter'].str[-4:] + df['Quarter'].str[:2])
pandas 中的字符串操作很慢,所以如果没有缺失值是可能的,请使用 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
给定像 2018-Q1
这样的四分之一格式,可以使用内置的 pd.to_datetime
函数。作为一般答案,必须处理可以存储季度观察值的多种方式(例如 2018:1
、2018:Q1
、20181
、Q1:2018
等) ,将数据强制转换为 supra 格式超出了我的回答范围。
但是给定一个格式化的系列:
formatted_series = formatted_series_supplier() ...
df['date'] = pd.to_datetime(formatted_series)
例如:
>>> pd.to_datetime(pd.Series(['2018-Q1']))
0 2018-01-01
dtype: datetime64[ns]
如果您要处理监管数据,这些数据几乎总是反映季度末而不是开始(即,您需要 2019-01-01,而不是 2019-03-31),您可以使用偏移量如下:
df['date'] = df['date'] + pd.offsets.QuarterEnd(0)
使用上面的示例,删除中间结果,
>>> pd.to_datetime(pd.Series(['2018-Q1'])) + pd.offsets.QuarterEnd(0)
0 2018-03-31
dtype: datetime64[ns]
请注意,如果您希望在同一季度内为结束日期正确编制索引,则必须向 QuarterEnd
提供 0
参数。否则,你会得到这样的东西:
>>> pd.to_datetime('2018-03-31') + pd.offsets.QuarterEnd()
Timestamp('2018-06-30 00:00:00')
编辑:
如果您要回答这个问题并且您的字符串看起来像 1996-Q1
,那么只需使用 pd.to_datetime(df['Quarter'])
将其转换为正确的 pandas 日期时间。这道题是要解决所有不是这个标准格式的季度日期。
原问题:
我正在寻找一种将 Q3 1996
转换为 pandas 日期时间(例如本例中的 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')
问题还在于季度和年份的顺序显然是错误的 pandas 无法进行简单处理。
谁能帮我找到一种更简洁的方法将 Q3 1996
转换为 pandas 日期时间?
您可以(并且应该)使用 pd.PeriodIndex
作为第一步,然后使用 PeriodIndex.to_timestamp
:
qs = df['Quarter'].str.replace(r'(Q\d) (\d+)', r'-')
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'-'), 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
使用前 4 个值切片 2
并转换为日期时间:
df['date'] = pd.to_datetime(df['Quarter'].str[-4:] + df['Quarter'].str[:2])
pandas 中的字符串操作很慢,所以如果没有缺失值是可能的,请使用 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
给定像 2018-Q1
这样的四分之一格式,可以使用内置的 pd.to_datetime
函数。作为一般答案,必须处理可以存储季度观察值的多种方式(例如 2018:1
、2018:Q1
、20181
、Q1:2018
等) ,将数据强制转换为 supra 格式超出了我的回答范围。
但是给定一个格式化的系列:
formatted_series = formatted_series_supplier() ...
df['date'] = pd.to_datetime(formatted_series)
例如:
>>> pd.to_datetime(pd.Series(['2018-Q1']))
0 2018-01-01
dtype: datetime64[ns]
如果您要处理监管数据,这些数据几乎总是反映季度末而不是开始(即,您需要 2019-01-01,而不是 2019-03-31),您可以使用偏移量如下:
df['date'] = df['date'] + pd.offsets.QuarterEnd(0)
使用上面的示例,删除中间结果,
>>> pd.to_datetime(pd.Series(['2018-Q1'])) + pd.offsets.QuarterEnd(0)
0 2018-03-31
dtype: datetime64[ns]
请注意,如果您希望在同一季度内为结束日期正确编制索引,则必须向 QuarterEnd
提供 0
参数。否则,你会得到这样的东西:
>>> pd.to_datetime('2018-03-31') + pd.offsets.QuarterEnd()
Timestamp('2018-06-30 00:00:00')