从Python(pandas)中的日期列获取周开始日期(星期一)?

yk9xbfzb  于 2022-10-22  发布在  Python
关注(0)|答案(5)|浏览(569)

我已经看到了很多关于如何使用日期字符串的帖子,但我正在尝试为 Dataframe 列做一些事情,到目前为止没有任何运气。我当前的方法是:从“myday”中获取工作日,然后偏移以获取星期一。

df['myday'] is column of dates. 
mydays = pd.DatetimeIndex(df['myday']).weekday
df['week_start'] = pd.DatetimeIndex(df['myday']) - pd.DateOffset(days=mydays)

但我得到TypeError:timedelta days组件不支持的类型:numpy.narray
如何从df专栏中获取每周开始日期?

yyhrrdl8

yyhrrdl81#

另一种选择:

df['week_start'] = df['myday'].dt.to_period('W').apply(lambda r: r.start_time)

这将“week_start”设置为“myday”中时间之前的第一个星期一。
您可以通过锚定偏移量选择不同的周开始,例如’W-THU’,将周开始时间改为周四。(感谢@Henry Ecker的建议)

zkure5ic

zkure5ic2#

虽然@knightofni和@Paul的解决方案都有效,但我倾向于避免在Pandas中使用apply,因为它通常比基于数组的方法慢。为了避免这种情况,在转换为datetime列(通过pd.to_datetime)之后,我们可以修改基于工作日的方法,只需将星期几转换为numpy timedelta64[D],方法是直接转换:

df['week_start'] = df['myday'] - df['myday'].dt.weekday.astype('timedelta64[D]')

或者按照@ribitskiyb的建议使用to_timedelta

df['week_start'] = df['myday'] - pd.to_timedelta(df['myday'].dt.weekday, unit='D').

使用60000个日期时间的测试数据,我使用新发布的Pandas 1.0.1给出了以下建议答案。

%timeit df.apply(lambda x: x['myday'] - datetime.timedelta(days=x['myday'].weekday()), axis=1)
>>> 1.33 s ± 28.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

%timeit df['myday'].dt.to_period('W').apply(lambda r: r.start_time)
>>> 5.59 ms ± 138 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

%timeit df['myday'] - df['myday'].dt.weekday.astype('timedelta64[D]')
>>> 3.44 ms ± 106 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

%timeit df['myday'] - pd.to_timedelta(df['myday'].dt.weekday, unit='D')
>>> 3.47 ms ± 170 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

这些结果表明,Pandas 1.0.1大大提高了基于to_period应用程序的方法的速度(vs Pandas<=0.25),但表明直接转换为时间增量(通过直接转换类型.astype('timedelta64[D]')或使用pd.to_timedelta)仍然是优越的。基于这些结果,我建议继续使用m1n 3o1p。

uqcuzwp8

uqcuzwp83#

(只是添加到n8yoder的答案中)
使用.astype('timedelta64[D]')对我来说似乎不那么易读——找到了一种仅使用Pandas功能的替代方法:

df['myday'] - pd.to_timedelta(arg=df['myday'].dt.weekday, unit='D')
zte4gxcn

zte4gxcn4#

它失败是因为pd.DateOffset需要一个整数作为参数(并且您正在给它一个数组)。只能使用DateOffset将日期列更改为相同的偏移量。
试试这个:

import datetime as dt

# Change 'myday' to contains dates as datetime objects

df['myday'] = pd.to_datetime(df['myday'])  

# 'daysoffset' will container the weekday, as integers

df['daysoffset'] = df['myday'].apply(lambda x: x.weekday())

# We apply, row by row (axis=1) a timedelta operation

df['week_start'] = df.apply(lambda x: x['myday'] - dt.TimeDelta(days=x['daysoffset']), axis=1)

我还没有真正测试过这段代码(没有样本数据),但这应该适用于您所描述的内容。
然而,您可能想看看pandas.Resample,它可能会提供更好的解决方案,具体取决于您要寻找的内容。

zynd9foi

zynd9foi5#

from datetime import datetime, timedelta

# Convert column to pandas datetime equivalent

df['myday'] = pd.to_datetime(df['myday']) 

# Create function to calculate Start Week date

week_start_date = lambda date: date - timedelta(days=date.weekday())

# Apply above function on DataFrame column

df['week_start_date'] = df['myday'].apply(week_start_date)

相关问题