我正在使用pandas在python中工作。我在一天内查询独特用户的外部数据源(例如每30天或每2天或每7天一次的唯一用户)。查询需要句点开始,句点结束和间隔(天数)。
例如,为了获得jan 1st的唯一用户,params是:
1月1日至1月1日(3天分组):
有时候我也需要多个时期。在所有情况下,一段时间可以在结束日期之后结束,但永远不会在结束之后开始。
例如,对于1月1日到1月1日的独特30天:
理想情况下,我会使用pandas.period_range()
,但由于它不接受freq
参数中的多个,我转向pandas.date_range()
。我正在迭代日期范围内的时间戳,如下所示:
import pandas
start_date = "2015-01-01"
end_date = "2015-01-03"
interval = 3
for timestamp in pandas.date_range(start_date , end_date , freq=str(interval)+"D"):
period_start = timesteamp.date()
period_end = period_start + datetime.timedelta(days=interval)
# query with period_start, period_end, interval
因此,当pandas生成的范围的最后一个元素位于end参数之后时,它会产生一个不必要的循环和我想要避免的不需要的查询。
问题是这样的调用:
pandas.date_range("2015-01-01", "2015-01-03", freq="3D")
返回:
<class 'pandas.tseries.index.DatetimeIndex'>
[2015-01-01, 2015-01-04]
Length: 2, Freq: 3D, Timezone: None
最后一个元素2015-01-04在2015-01-03结束限制之后。当频率短于或长于实际期间(在这种情况下为2天或4天)时,不会发生这种情况:
>>> pandas.date_range("2015-01-01", "2015-01-03", freq="2D")
<class 'pandas.tseries.index.DatetimeIndex'>
[2015-01-01, 2015-01-03]
Length: 2, Freq: 2D, Timezone: None
>>> pandas.date_range("2015-01-01", "2015-01-03", freq="4D")
<class 'pandas.tseries.index.DatetimeIndex'>
[2015-01-01]
Length: 1, Freq: 4D, Timezone: None
我试图了解close参数,但描述对我来说有点神秘。这三个值中没有一个(“右”,“左”,“无”)似乎给出了我所追求的东西。
我测试了3个可能的closed=
值来观察不同的输出:
>>> pandas.date_range("2015-01-01", "2015-01-03", freq="3D", closed="left")
<class 'pandas.tseries.index.DatetimeIndex'>
[2015-01-01]
Length: 1, Freq: 3D, Timezone: None
这似乎是理想的结果。但是在freq
比起始和结束之间的时间长的情况下,它返回一个包含0个元素的范围。
>>> pandas.date_range("2015-01-01", "2015-01-01", freq="10D", closed="left")
<class 'pandas.tseries.index.DatetimeIndex'>
Length: 0, Freq: 10D, Timezone: None
我希望:
<class 'pandas.tseries.index.DatetimeIndex'>
[2015-01-01]
Length: 1, Freq: 10D, Timezone: None
我唯一一次看到结果为空的情况是freq
的乘数是否为0(即“0D”,“0H”,“0W”)。这已经引发了错误,所以在practice date_range()
中应始终至少返回它的起始值。如果end参数出现在频率结束之前,则范围将只包含一个时间戳。
答案 0 :(得分:0)
您可以设置多个date_range并使用pandas.DatetimeIndex.union联合所有日期时间
答案 1 :(得分:0)
我认为你的间隔语义有点困惑,熊猫在这里做了一些合理的事情。
考虑你的最后一个例子:
>>> pandas.date_range("2015-01-01", "2015-01-01", freq="10D", closed="left")
你写的是你期望的:
<class 'pandas.tseries.index.DatetimeIndex'>
[2015-01-01]
Length: 1, Freq: 10D, Timezone: None
考虑2015-01-04
之类的日期。一方面,这将是 in 此DatetimeIndex中的第一个(唯一)时间间隔。另一方面,此日期将在您提供的结束日期之后下降,这似乎与您原始date_range
电话中的时间间隔规格相矛盾。
或换句话说,从1月1日到1月2日间隔30天是什么意思?
如果您希望区间索引自动扩展到包含开始日期加间隔长度的结束日期,我认为您需要编写一个函数来执行此操作。
def nonempty_date_range(start, end, freq, closed=None):
""" Return a pandas.DatetimeIndex containing at least one interval. In some cases, the interval will extend beyond 'end'. """
start = pandas.to_datetime(start)
end = pandas.to_datetime(end)
length = pandas.to_timedelta(freq)
end = max(end, start + length)
return pandas.date_range(start=start, end=end, freq=freq, closed=closed)
结果:
# Example from question
>>> pandas.date_range("2015-01-01", "2015-01-01", freq="10D", closed="left")
DatetimeIndex([], dtype='datetime64[ns]', freq='10D')
以上功能:
>>> nonempty_date_range("2015-01-01", "2015-01-01", freq="10D", closed="left")
DatetimeIndex(['2015-01-01'], dtype='datetime64[ns]', freq='10D')