Pandas -根据从日期列导出的星期几更改周数

3ks5zfa0  于 2023-01-24  发布在  其他
关注(0)|答案(4)|浏览(131)

假设我有下面的 Dataframe 。
| 日期|周数|工作日|
| - ------|- ------|- ------|
| 2023年1月1日|1个|星期日|
| 2023年2月1日|1个|星期一|
| 2023年4月1日|1个|星期三|
| 2023年1月5日|1个|星期四|
| 2023年1月7日|1个|星期六|
我知道第三行是在第一周,但是我想使用星期三作为截止点,因为到这个时候已经过去了半周,所以接下来的几天应该移到下周,比如下面。
| 日期|周数|工作日|
| - ------|- ------|- ------|
| 2023年1月1日|1个|星期日|
| 2023年2月1日|1个|星期一|
| 2023年4月1日|1个|星期三|
| 2023年1月5日|第二章|星期四|
| 2023年1月7日|第二章|星期六|
到目前为止,我的尝试都是零星的成功,这也是一个边缘的情况,但一组数据似乎容易出现这种奇怪的情况,所以我想要一个解决方案。
我脑子里的想法是这样的:

if Weekday-Number > 3 then Week_Num + 1
else do nothing

我理解如何分别做每一部分,但把它们放在一起是我卡住的地方。任何帮助都将不胜感激。

wdebmtf2

wdebmtf21#

"Shortly"(一行程序),您可以使用cumsum()

df['Week_Num'] = df['WeekDay'].eq('Wednesday').cumsum().add(1).shift(1).fillna(1).astype(int)

输入示例:

df = pd.DataFrame.from_dict({
    'Date': ['01/01/23', '02/01/23', '04/01/23', '05/01/23', '07/01/23', '07/01/23', '07/01/23', '07/01/23', '07/01/23', '07/01/23'],
    'WeekDay': ['Sunday', 'Monday', 'Wednesday', 'Thursday', 'Saturday', 'Wednesday', 'Thursday', 'Saturday', 'Wednesday', 'Thursday']
})

输出:

Date    WeekDay  Week_Num
0  01/01/23     Sunday         1
1  02/01/23     Monday         1
2  04/01/23  Wednesday         1
3  05/01/23   Thursday         2
4  07/01/23   Saturday         2
5  07/01/23  Wednesday         2
6  07/01/23   Thursday         3
7  07/01/23   Saturday         3
8  07/01/23  Wednesday         3
9  07/01/23   Thursday         4

解释:

1.我们将新列Week_Num引入df
1.我们使用cumsum(),当我们满足由.eq表示的特定要求时,cumsum()会累加一个值

  1. .eq部分是如果我们遇到工作日"星期三"
    1.我们给每一行加1,因为cumsum从0开始,我们想从1开始。
    1.我们将 Dataframe 中的每一行向下移动1,仅更改不包括"星期三"的行
    1.因为我们将每一行向下移动,那么第一行将为NaN-所以我们用week_num 1填充它
    1.我们使用astype(int)将行转换为整数值
cnh2zyt3

cnh2zyt32#

没有使用当前数据框的简单、非迭代的解决方案。如果WeekDay列表示为数字而不是文本,则简单的df.loc[]语句将给予所需的结果。

df.loc[df["WeekDay"] > 4, "Week_Num"] += 1

这就是说,找到Weekday〉4的行,并将Week_Num值递增1。
使用您发布的数据框,可以将一个较慢的迭代解决方案(不推荐)与datetime库中的weekday()函数沿着使用。

#loop through each data frame row
for i, row in df.iterrows():
    #if the date is past wednesday, increment week_num
    if(row["dates"].weekday() > 4):
        df.at[i, "week_num"] += 1

代码会遍历每个行项,并基于if语句递增Week_Num。使用此方法还意味着WeekDay列已过时,因为datetime允许您从日期获取工作日编号。

oxf4rvwz

oxf4rvwz3#

可以使用PandasTimedelta对象。
只需使用Date列,就可以将其转换为pandas datetime对象(实际上可以使用它来创建WeekDay列)。

>>> import pandas as pd
>>> df = pd.DataFrame( 
    data = {"Date":["1/1/23", "2/1/23", "4/1/23", "5/1/23", "7/1/23" ]}
)
>>> df.Date = pd.to_datetime( df.Date, dayfirst=True )
>>> df

    Date
0   2023-01-02
1   2023-01-03
2   2023-01-04
3   2023-01-05

创建WeekDay列:

>>> dayOfWeekMap = { 0: "Monday", 1: "Tuesday", 2: "Wednesday", 3: "Thursday", 4: "Friday",
                5: "Saturday", 6: "Sunday" }
>>> df["WeekDay"] = df.Date.dt.dayofweek.map( dayOfWeekMap )
>>> df

    Date    WeekDay
0   2023-01-01  Sunday
1   2023-01-02  Monday
2   2023-01-04  Wednesday
3   2023-01-05  Thursday
4   2023-01-07  Saturday

最后,获得自定义截止日期的周数。首先,定义您想要开始的日期。对于您的测试数据,我将从2023年12月28日星期三开始,因此3/1/2023是Week_Num = 1,但4/1/2023是Week_Num = 2

>>> start_date = pd.to_datetime( "28/12/2022", dayfirst=True )
>>> df["Week_Num"] = ( ( df.Date - start_date ).dt.days // 7 ).astype( int ) + 1
>>> df

    Date        WeekDay Week_Num
0   2023-01-01  Sunday      1
1   2023-01-02  Monday      1
2   2023-01-04  Wednesday   2
3   2023-01-05  Thursday    2
4   2023-01-07  Saturday    2

这里发生了什么:我们将观察中的日期与开始日期之间的天数差除以7(因此,开始日期后6天为0,开始日期后7天为1,开始日期后8天为1),然后加1,使计数器从1开始。

ddrv8njm

ddrv8njm4#

列的数据类型是我最初忽略的,我从答案中提取了一些片段,并编写了以下代码,这可能效率稍低,但似乎确实为该数据集生成了正确的输出。

df['week_num'] = df['Date'].dt.strftime('%V')
 df['Year'] = df['Date'].dt.strftime('%Y')
 df["WeekDay"] = df.Date.dt.dayofweek
 df['day_of_week'] = df['Date'].dt.day_name()
 df['week_num'] = df['week_num'].astype('int')
 df.loc[df["WeekDay"] > 3, "week_num"] += 1

由于数据作为一个整体涵盖了几个年份,我也在中添加了年份。我将用完整的df测试它,看看是否有任何错误出现,并评论这种方法是否有效。

相关问题