Python 熊猫:换天

Python 熊猫:换天,python,pandas,Python,Pandas,我有一个datetime格式的系列,需要为每个条目将日期更改为1。我想到了许多简单的解决方案,但没有一个对我有效。目前,唯一有效的方法是 将序列设置为索引 从索引中查询月份和年份 使用年、月和1重建新的时间序列 不会那么复杂吧?有一个月的开始,但不幸的是,这是一个偏移量,在这里没有用。该方法似乎没有set()函数,当序列是列而不是索引本身时,功能甚至更少 唯一相关的问题是,但这里使用的技巧不适用。您可以使用。应用和日期时间。替换,例如: import pandas as pd from da

我有一个
datetime
格式的系列,需要为每个条目将日期更改为
1
。我想到了许多简单的解决方案,但没有一个对我有效。目前,唯一有效的方法是

  • 将序列设置为索引
  • 从索引中查询月份和年份
  • 使用年、月和1重建新的时间序列
不会那么复杂吧?有一个月的开始,但不幸的是,这是一个
偏移量
,在这里没有用。该方法似乎没有
set()
函数,当序列是列而不是索引本身时,功能甚至更少


唯一相关的问题是,但这里使用的技巧不适用。

您可以使用
。应用
日期时间。替换
,例如:

import pandas as pd
from datetime import datetime

ps = pd.Series([datetime(2014, 1, 7), datetime(2014, 3, 13), datetime(2014, 6, 12)])
new = ps.apply(lambda dt: dt.replace(day=1))
给出:

0   2014-01-01
1   2014-03-01
2   2014-06-01
dtype: datetime64[ns]

另一个答案是有效的,但无论何时使用
apply
,代码都会慢很多。通过为一个系列编写一个快速矢量化的日期时间替换,我能够获得8.5倍的加速

def vec_dt_replace(系列,年=无,月=无,日=无):
返回pd.to_datetime(
{'year':series.dt.year如果year不是其他年份,
“月”:series.dt.month如果月份不是其他月份,
“day”:series.dt.day(如果day不是其他日期})
适用于:

%timeit dtseries.apply(lambda dt: dt.replace(day=1))
# 4.17 s ± 38.3 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
矢量化:

%timeit vec_dt_replace(dtseries, day=1)
# 491 ms ± 6.48 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
请注意,尝试将日期更改为不存在的日期可能会遇到错误,例如尝试将2012-02-29更改为2013-02-29。使用的
错误
参数忽略或强制它们

数据生成:生成具有100万个随机日期的序列:

将熊猫作为pd导入
将numpy作为np导入
#生成随机日期。修改自:https://stackoverflow.com/a/50668285
def pp(开始、结束、n):
start\u=start.value//10**9
end\u=end.value//10**9
返回pd系列(
(10**9*np.random.randint(start\u,end\u,n)).view('M8[ns]'))
起始日期=截止日期时间('2015-01-01')
结束=截止日期时间(2018-01-01)
dtseries=pp(开始,结束,1000000)
#删除时间组件
dtseries=dtseries.dt.normalize()

另外两个答案很有效,但都不是很优雅,也不符合
熊猫库的精神。相反,考虑一下这一点,在我的测试中,凯尔-巴伦的矢量化答案也稍快一点。它是一个单行程序,不需要定义任何外部函数,是矢量化的,并且保持在
pandas
生态系统中:

将熊猫作为pd导入
dtseries.dt.to_period('M').dt.to_timestamp()
这种方法还有一个额外的好处,就是支持许多其他频率,例如每周(
'W'
)或工作日(
'B'
),使用上述矢量化方法实现这些频率更为困难

您可以找到各种其他频率的缩写

当然,这假定
dtseries
是一个日期时间序列,如果不是,您可以使用
pd.轻松地将其转换为_datetime(my_series)

此解决方案还允许在使用各种偏移时具有很大的灵活性。例如,要使用月的第十天:

从pandas.tseries.offset导入日期offset
dtseries.dt.to_period('M').dt.to_timestamp()+日期偏移量(天=10)
我建议你检查一下房间。补偿熊猫提供了许多相当复杂的补偿支持,例如工作日、假期、工作时间等。。。按照@KyleBarron和@JonClements的回答,手工实现这些将非常麻烦。考虑这个例子,例如从月初获得5个工作日的日期偏移:

来自pandas.tseries.com导入工作日
dtseries.dt.to_period('M').dt.to_timestamp()+工作日(n=5)

对于一个保持在熊猫生态系统内的向量化解决方案,请考虑下面的答案。注意,这只适用于你想要落到预定义频率的特殊情况。如果您想将所有日期设置为,比如说,第10天,那么我看不到使用此选项的方法。@KyleBarron不,这仍然有效。您只需添加一个。请参阅我的编辑:)@KyleBarron事实上,我认为我的解决方案在处理复杂偏移量时反而更加灵活。例如,你会如何处理工作日案例?这些都是很好的观点,编辑很好地解释了这一点。从一个简单的测试来看,你的答案比我的快5%。我不再研究熊猫中的日期,但我认为你的是最普遍的。