在Python中,如果将日期列表作为DateTime对象,如何计算每个月的第一个星期五?

在Python中,如果将日期列表作为DateTime对象,如何计算每个月的第一个星期五?,python,pandas,dataframe,datetime,Python,Pandas,Dataframe,Datetime,假设在Python中有一个DateTimeIndex对象存储为trading\u days: DatetimeIndex(['2014-01-02', '2014-01-03', '2014-01-06', '2014-01-07', '2014-01-08', '2014-01-09', '2014-01-10', '2014-01-13', '2014-01-14', '2014-01-15', ...

假设在Python中有一个
DateTimeIndex
对象存储为
trading\u days

DatetimeIndex(['2014-01-02', '2014-01-03', '2014-01-06', '2014-01-07',
               '2014-01-08', '2014-01-09', '2014-01-10', '2014-01-13',
               '2014-01-14', '2014-01-15',
               ...
               '2017-12-15', '2017-12-18', '2017-12-19', '2017-12-20',
               '2017-12-21', '2017-12-22', '2017-12-26', '2017-12-27',
               '2017-12-28', '2017-12-29'],
              dtype='datetime64[ns]', length=1007, freq=None)
我想计算这个DateTime对象中每个月的第一个星期五。我想要的输出是另一个DateTime对象,其中包含第一个星期五的这些日期

我的尝试如下:

all_fridays = trading_days[trading_days.day_name() == 'Friday']
first_fridays = all_fridays[np.remainder(np.arange(len(all_fridays)), 4) == 0]
但当然,如果某个月有5个星期五,则此代码将失败。 例如,我从上面的代码中得到的输出是

DatetimeIndex(['2014-01-03', '2014-01-31', '2014-02-28', '2014-03-28',
               '2014-05-02', '2014-05-30', '2014-06-27', '2014-08-01',
               '2014-08-29', '2014-09-26', '2014-10-24', '2014-11-21',
               '2014-12-19', '2015-01-16', '2015-02-13', '2015-03-13',
               '2015-04-17', '2015-05-15', '2015-06-12', '2015-07-17',
               '2015-08-14', '2015-09-11', '2015-10-09', '2015-11-06',
               '2015-12-04', '2016-01-15', '2016-02-12', '2016-03-11',
               '2016-04-15', '2016-05-13', '2016-06-10', '2016-07-08',
               '2016-08-05', '2016-09-02', '2016-09-30', '2016-10-28',
               '2016-11-25', '2016-12-23', '2017-01-20', '2017-02-17',
               '2017-03-17', '2017-04-21', '2017-05-19', '2017-06-16',
               '2017-07-14', '2017-08-11', '2017-09-08', '2017-10-06',
               '2017-11-03', '2017-12-01', '2017-12-29'],
              dtype='datetime64[ns]', freq=None)
2014年1月很容易出现我刚才描述的错误。然后一切都搞砸了


我怎样才能有效地完成它?我觉得熊猫应该已经内置了类似的东西,但我找不到。非常感谢

无法100%确定如何重新创建示例DatetimeIndex,但我们将从一个简单的
bdate\u范围开始

子集到星期五,然后在年-月期间删除重复项

import pandas as pd
trading_days = pd.bdate_range('2014-01-02', freq='C', periods=1007, weekmask='Mon Tue Wed Thu Fri')

fridays = trading_days[trading_days.dayofweek == 4]
fridays = fridays[~fridays.to_period('M').duplicated()]

#DatetimeIndex(['2014-01-03', '2014-02-07', '2014-03-07', '2014-04-04',
#               '2014-05-02', '2014-06-06', '2014-07-04', '2014-08-01',
#               ...
#               '2017-05-05', '2017-06-02', '2017-07-07', '2017-08-04',
#               '2017-09-01', '2017-10-06', '2017-11-03'],
#              dtype='datetime64[ns]', name='date', freq=None)

无法100%确定如何重新创建示例DatetimeIndex,但我们将从一个简单的
bdate\u范围开始

子集到星期五,然后在年-月期间删除重复项

import pandas as pd
trading_days = pd.bdate_range('2014-01-02', freq='C', periods=1007, weekmask='Mon Tue Wed Thu Fri')

fridays = trading_days[trading_days.dayofweek == 4]
fridays = fridays[~fridays.to_period('M').duplicated()]

#DatetimeIndex(['2014-01-03', '2014-02-07', '2014-03-07', '2014-04-04',
#               '2014-05-02', '2014-06-06', '2014-07-04', '2014-08-01',
#               ...
#               '2017-05-05', '2017-06-02', '2017-07-07', '2017-08-04',
#               '2017-09-01', '2017-10-06', '2017-11-03'],
#              dtype='datetime64[ns]', name='date', freq=None)

当您找到数组的第一个星期五时,下面的逻辑可以帮助您

假设第一个星期五是2014-01-03,然后检查末尾第4位的数字(我考虑将“-”作为一个位置),现在将28添加到当前指数中。如果收到的日期在倒数第4位的数字与前一个相同,则在索引中再添加7,该索引将是下个月的第一个星期五,否则,通过添加28获得的索引将是下个月的第一个星期五

在这里,您不需要检查第5位,因为过去3个月,即10、11和12,所有位置的最后一位数字都与前一位不同


使用pyhton中的if-else条件可以轻松实现上述所有解释。

当您找到数组的第一个星期五时,以下逻辑可以帮助您

假设第一个星期五是2014-01-03,然后检查末尾第4位的数字(我考虑将“-”作为一个位置),现在将28添加到当前指数中。如果收到的日期在倒数第4位的数字与前一个相同,则在索引中再添加7,该索引将是下个月的第一个星期五,否则,通过添加28获得的索引将是下个月的第一个星期五

在这里,您不需要检查第5位,因为过去3个月,即10、11和12,所有位置的最后一位数字都与前一位不同


使用pyhton中的if-else条件可以轻松实现上述所有解释。

这里有一个简单的函数,它将从pandas DatetimeIndex中提取每个月的第一个星期五(或每个月的第四个星期四,或…)。这是使用
itertools.groupby()函数的借口

import pandas as pd
from itertools import groupby

def get_one_date_per_month(dates, rank='first', day_name='Friday'):
    rank_to_idx = {'first': 0, 'second': 1, 'third': 2, 'fourth': 3, 'last': -1}
    idx = rank_to_idx[rank]
    dates = [d
             for d in dates
             if d.day_name() == day_name]
    
    filtered_dates = []
    for k, g in groupby(dates, key=lambda x: x.strftime('%Y-%m')):
        t = list(g)
        filtered_dates.append(t[idx])
        
    return filtered_dates
使用如下函数:

# use your list of trading days, or `dates` for illustration:
dates = pd.date_range(start='2014-01-01', end='2017-12-31', freq='D')

get_one_date_per_month(dates)[:3]

# results are:
[Timestamp('2014-01-03 00:00:00', freq='D'),
 Timestamp('2014-02-07 00:00:00', freq='D'),
 Timestamp('2014-03-07 00:00:00', freq='D')]

下面是一个简单的函数,它将从pandas DatetimeIndex中提取每个月的第一个星期五(或每个月的第四个星期四,或…)。这是使用
itertools.groupby()函数的借口

import pandas as pd
from itertools import groupby

def get_one_date_per_month(dates, rank='first', day_name='Friday'):
    rank_to_idx = {'first': 0, 'second': 1, 'third': 2, 'fourth': 3, 'last': -1}
    idx = rank_to_idx[rank]
    dates = [d
             for d in dates
             if d.day_name() == day_name]
    
    filtered_dates = []
    for k, g in groupby(dates, key=lambda x: x.strftime('%Y-%m')):
        t = list(g)
        filtered_dates.append(t[idx])
        
    return filtered_dates
使用如下函数:

# use your list of trading days, or `dates` for illustration:
dates = pd.date_range(start='2014-01-01', end='2017-12-31', freq='D')

get_one_date_per_month(dates)[:3]

# results are:
[Timestamp('2014-01-03 00:00:00', freq='D'),
 Timestamp('2014-02-07 00:00:00', freq='D'),
 Timestamp('2014-03-07 00:00:00', freq='D')]

不确定这比已经发布的其他答案好。但根据您的问题,我从
DatetimeIndex
中的日期开始:

index = pd.DatetimeIndex(pd.date_range('2014-01-02', '2017-12-19'))  # some dates
dates_by_month = index.groupby(index.to_period("M"))    
first_fridays = pd.Series({period: dates[dates.weekday == 4][0]
                           for period, dates in dates_by_month.items()})
first_fridays.head()

2014-01   2014-01-03
2014-02   2014-02-07
2014-03   2014-03-07
2014-04   2014-04-04
2014-05   2014-05-02
Freq: M, dtype: datetime64[ns]

不确定这比已经发布的其他答案好。但根据您的问题,我从
DatetimeIndex
中的日期开始:

index = pd.DatetimeIndex(pd.date_range('2014-01-02', '2017-12-19'))  # some dates
dates_by_month = index.groupby(index.to_period("M"))    
first_fridays = pd.Series({period: dates[dates.weekday == 4][0]
                           for period, dates in dates_by_month.items()})
first_fridays.head()

2014-01   2014-01-03
2014-02   2014-02-07
2014-03   2014-03-07
2014-04   2014-04-04
2014-05   2014-05-02
Freq: M, dtype: datetime64[ns]