pandas 生成两个日期列之间的所有月份

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

我正在尝试生成两个日期列之间的所有月份。我有以下 Dataframe :
| 开始日期|结束日期|
| - ------|- ------|
| 二○一○年一月十五日|二零一零年八月十五日|
| 二○ ○九年一月七日|二○一○年一月十三日|
我想要的输出是添加一个月份列,其中包括StartDate和EndDate列之间所有可用的月份。
输出:
| 开始日期|结束日期|月份|
| - ------|- ------|- ------|
| 二○一○年一月十五日|二零一零年八月十五日|一、二、三、四、五、六、七、八|
| 二○ ○九年一月七日|二○一○年一月十三日|七、八、九、十、十一、十二、一|
我试着写了这段代码,但它并不像我想要的那样工作。

date_range= lambda x:range (x['StartDate'].month,x['EndDate'].month+1)
df=df.assign(month=df.apply(date_range, axis=1)
e0uiprwp

e0uiprwp1#

我们可以使用 * dateutil. rrule * 来完成此操作

    • 代码:**
from dateutil.rrule import rrule, MONTHLY
def month_between_dates(start_date, end_date):
    months_between = [str(dt.month) for dt in rrule(MONTHLY, 
                                dtstart = start_date.replace(day=1), 
                                until = end_date.replace(day=1))]
    return ",".join(months_between)
in_df["Month"] = in_df.apply(lambda x: month_between_dates(x["StartDate"],
                                                           x["EndDate"]), axis=1)
    • 输出:**
StartDate    EndDate            Month
2010-01-15 2010-08-15  1,2,3,4,5,6,7,8
2009-07-01 2010-01-15 7,8,9,10,11,12,1
    • 代码说明:**
months_between = [str(dt.month) for dt in rrule(MONTHLY, 
                            dtstart = start_date.replace(day=1), 
                            until = end_date.replace(day=1))]
    • start_date. replace(day = 1)**将日期转换为第一天。
    • 对于rrule中的dt(MONTHLY,dtstart =开始日期,until =结束日期)**在开始日期和结束日期之间的月份中迭代。
2hh7jdfx

2hh7jdfx2#

Series.dt.to_period创建日期时间为的月份期间,然后按压缩的Series创建period_range,并提取月份:

s = pd.to_datetime(df['StartDate']).dt.to_period('m')
e = pd.to_datetime(df['EndDate']).dt.to_period('m')

df=df.assign(month=[pd.period_range(y, x).month.tolist() for x, y in zip(e, s)])

print (df)
    StartDate     EndDate                     month
0  01-15-2010  08-15-2010  [1, 2, 3, 4, 5, 6, 7, 8]
1  07-01-2009  01-13-2010  [7, 8, 9, 10, 11, 12, 1]

如果需要通过,连接字符串,请用途:

df=df.assign(month=[','.join(pd.period_range(y, x).month.astype(str)) 
                    for x, y in zip(e, s)])

print (df)
    StartDate     EndDate             month
0  01-15-2010  08-15-2010   1,2,3,4,5,6,7,8
1  07-01-2009  01-13-2010  7,8,9,10,11,12,1
7eumitmz

7eumitmz3#

以下是仅使用pandas.date_range和numpy.vectorize的矢量化解决方案

import numpy as np
import pandas as pd

input_df = pd.DataFrame(
    {
        'StartDate': ['01-15-2010', '07-01-2009'],
        'EndDate': ['08-15-2010', '01-13-2010']
    }
)
input_df = input_df.apply(pd.to_datetime)

def create_months_between(from_timestmp: pd.Timestamp, to_timestamp: pd.Timestamp, return_string=False) -> str:
    """returns a list of months between dates

    Args:
        from_timestmp (pd.Timestamp): datetime from
        to_timestamp (pd.Timestamp): datetime to
        return_string (bool, optional): Retrun a string of months, not a list. Defaults to False.

    Returns:
        str: list of ints if return_string==False, string of values if return_string==True
    """

    list_result = [value.month
                   for value
                   in pd.date_range(
                       from_timestmp,
                       to_timestamp,
                       freq='M',
                       normalize=True
                   )
                   ]
    list_result.append(np.datetime64(to_timestamp).astype(
        'datetime64[M]').astype(int) % 12 + 1)

    result_string = ','.join([str(value) for value in list_result])
    return result_string

input_df.columns
input_df['Month'] = np.vectorize(create_months_between)(
    input_df['StartDate'], input_df['EndDate'])
input_df

它返回一个表,看起来像您描述的那个。
| 开始日期|结束日期|月份|
| - ------|- ------|- ------|
| 2010年1月15日|2010年8月15日|一、二、三、四、五、六、七、八|
| 二○ ○九年七月一日|2010年1月13日|七、八、九、十、十一、十二、一|

相关问题