我有两个日期列“开始日期”和“结束日期”,我想查找年份和这两个日期之间每个月的天数。我可以找到一年,但不知道如何找到每个月的天数。不确定获取此o / p是否可行。
from pandas import DataFrame
import re
df = {'Id': ['1','2','3','4','5'],
'Item': ['A','B','C','D','E'],
'StartDate': ['2019-12-10', '2019-12-01', '2019-01-01', '2019-05-10', '2019-03-10'],
'EndDate': ['2019-12-30' ,'2019-12-31','2019-03-30','2019-11-30','2019-06-10']
}
df = DataFrame(df,columns= ['Id', 'Item','StartDate','EndDate'])
答案 0 :(得分:1)
我想出了使用string.empty
和pd.date_range
的解决方案。您需要将resample
和StartDate
列都转换为datetime dtype
EndDate
最后连接回原始数据框
df['StartDate'] = pd.to_datetime(df['StartDate'])
df['EndDate'] = pd.to_datetime(df['EndDate'])
def days_of_month(x):
s = pd.date_range(*x, freq='D').to_series()
return s.resample('M').count().rename(lambda x: x.month)
df1 = df[['StartDate', 'EndDate']].apply(days_of_month, axis=1).fillna(0)
Out[1036]:
1 2 3 4 5 6 7 8 9 10 11 12
0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 21.0
1 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 31.0
2 31.0 28.0 30.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
3 0.0 0.0 0.0 0.0 22.0 30.0 31.0 31.0 30.0 31.0 30.0 0.0
4 0.0 0.0 22.0 30.0 31.0 10.0 0.0 0.0 0.0 0.0 0.0 0.0
答案 1 :(得分:0)
您可以结合使用 vectorization与pandas和numpy 的组合,以实现以下目的。为了方便使用,下面提供了自定义功能。由于它使用矢量化,因此应该很快。
注意:此处使用的假设基于示例数据:
如果您有不同年份的数据,则需要将此数据应用于那里的每年数据。另外,如果开始日期和结束日期位于不同的年份,则必须对此采用相应的方法。由于此处提出的问题并未说明该要求,因此我将本实现作为任何对将其应用到跨度跨度数据集感兴趣的人的指南。
如果您想在jupyter笔记本环境中试用此解决方案,可以在github上here进行访问。它还具有Google Colaboratory链接。因此,您也可以直接在Google Colab Notebook中打开它。
# Updated DataFrame
df = process_dataframe(df) # custom function
display(df.head())
在Google Colab环境中通过pandas==0.25.3
和numpy==0.17.4
进行了测试。
import numpy as np
import pandas as pd
#from pandas.tseries.offsets import MonthEnd
from IPython.display import display
# Dummy Data
df = {'Id': ['1','2','3','4','5'],
'Item': ['A','B','C','D','E'],
'StartDate': ['2019-12-10', '2019-12-01', '2019-01-01', '2019-05-10', '2019-03-10'],
'EndDate': ['2019-12-30' ,'2019-12-31','2019-03-30','2019-11-30','2019-06-10']
}
df = pd.DataFrame(df,columns= ['Id', 'Item','StartDate','EndDate'])
# Function for Processing the DataFrame
def process_dataframe(df):
"""Returns the updated dataframe. """
df.StartDate = pd.to_datetime(df.StartDate)
df.EndDate = pd.to_datetime(df.EndDate)
month_ends = pd.date_range(start='2019-01', freq='M', periods=12)
month_headers = month_ends.month_name().str.upper().str[:3].tolist()
month_days = month_ends.day.to_numpy()
month_nums = (np.arange(12) + 1)
# Evaluate expressions to avoid multiple times evaluation
start_date_month_num = df.StartDate.dt.month.to_numpy().reshape(-1,1)
end_date_month_num = df.EndDate.dt.month.to_numpy().reshape(-1,1)
#start_month_days = pd.to_datetime(df.StartDate, format="%Y%m") + MonthEnd(1) - df.StartDate
# start_month_days.dt.days.to_numpy()
# Number of days not in the end_month
end_month_days_excluded = month_days[df.EndDate.dt.month.to_numpy() - 1] - df.EndDate.dt.day.to_numpy()
# Determine the months that fall within the start and end dates (inclusive
# of start and end months) and then calculate the number of days in each
# month.
# add all days for relevant months
result = ((start_date_month_num <= month_nums) & \
(end_date_month_num >= month_nums)).astype(int) \
* month_days.reshape(1,-1)
# subtract number of days not in starting month
result = result + \
(-1) * (start_date_month_num == month_nums).astype(int) \
* (df.StartDate.dt.day.to_numpy() - 1).reshape(-1,1)
# subtract number of days not in ending month
result = result + \
(-1) * (end_date_month_num == month_nums).astype(int) \
* end_month_days_excluded.reshape(-1,1)
return pd.merge(df, pd.DataFrame(result, columns = month_headers), left_index=True, right_index=True)
原始DataFrame :
# Original DataFrame
display(df.head())