[英]Pyspark - generate a dates column having all the days between two given dates and add it to an existing dataframe
[英]Generate all Months between two dates column
我正在嘗試生成兩個日期列之間的所有月份。 我有以下 dataframe:
開始日期 | 結束日期 |
---|---|
01-15-2010 | 08-15-2010 |
07-01-2009 | 01-13-2010 |
我想要的輸出是添加一個月份列,其中包括 StartDate 和 EndDate 列之間可用的所有月份。
Output:
開始日期 | 結束日期 | 月 |
---|---|---|
01-15-2010 | 08-15-2010 | 1,2,3,4,5,6,7,8 |
07-01-2009 | 01-13-2010 | 7,8,9,10,11,12,1 |
我嘗試編寫這段代碼,但它沒有按我想要的那樣工作。
date_range= lambda x:range (x['StartDate'].month,x['EndDate'].month+1)
df=df.assign(month=df.apply(date_range, axis=1)
我們可以使用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)
Output:
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)將日期轉換為第一天。
for dt in rrule(MONTHLY, dtstart = start_date,until = end_date)在開始日期和結束日期之間的月份中迭代。
通過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
這是基於僅使用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-01-15 | 2010-08-15 | 1,2,3,4,5,6,7,8 |
2009-07-01 | 2010-01-13 | 7,8,9,10,11,12,1 |
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.