如何按连续季节计算大熊猫的日期月



我有一个大的时间序列数据框架。该列已被格式化为日期时间。如

2017-10-06T00:00:00+00:00
2020-04-29 00:00:00+00:00

我想绘制每个季节的样本数。例如:值为该季节的样本计数数。

1997 Winter 4
1997 Spring 8
1997 Summer 8
...
2020 Winter 32

我确实做了一些搜索,并意识到我可以创建一个字典将月份转换为季节。然而,自"真正的冬季"以来,最棘手的部分包含了两年的数据。例如,1997年的冬天实际上应该包含1997年12月、1998年1月和1998年2月。

请注意,我想把'1997年1月,1997年2月'从1997年冬季中排除,因为它们是'1996年冬季'。

我想知道最有效的方法是什么?它不一定要命名为'1997 winter',只要计数数字从开始到结束是连续的,任何索引都应该对我有效。

多谢!

有一个快速的方法来解决它,但它不是很正统…您创建了一个列'season',并使用np.where()来分配季节。一开始,你说前3个月是冬天,后3个月是春天,以此类推。然后,对这一列做一个位移(-1)使它后退一行。然后,你得到了你的季节(只要填满最后一个nan)。然后你可以用一种懒惰的方式来解决你的问题。如果你对代码不满意,告诉我,我会编辑它。

编辑:

我假设日期在索引中。如果不是,你应该应用dt。Month而不是。Month。我分解它使它更清晰

_condtion_spring = (df.index.month>=4)&(df.index.month<=6)
_condition_summer = (df.index.month>7)&(df.index.month<=9)
_condition_automn = (df.index.month>=10)@(df.index.month<=12)
df['Season'] = np.where(_condition_winter,'Winter',np.where(_condtion_spring,'Spring',np.where(_condition_summer,'Summer',np.where(_condition_automn,'Automn',np.nan))))
df['Season'] = df['Season'].shift(-1).fillna(method='ffill')

编辑2:

这里有一个完整的例子:

dates = pd.date_range("1983-09-01","1985-12-31",freq="1M")
df = pd.DataFrame(np.random.randint(100, 200,size=28)/100,index =dates,columns=["Sample"])
df = df.sort_index()
_condition_winter = (df.index.month>=1)&(df.index.month<=3)
_condtion_spring = (df.index.month>=4)&(df.index.month<=6)
_condition_summer = (df.index.month>=7)&(df.index.month<=9)
_condition_automn = (df.index.month>=10)@(df.index.month<=12)
df['Season'] = np.where(_condition_winter,'Winter',np.where(_condtion_spring,'Spring',np.where(_condition_summer,'Summer',np.where(_condition_automn,'Automn',np.nan))))
df['Season'] = df['Season']+'_'+df.index.strftime(date_format='%Y')
df['Season'] = df['Season'].shift(-1).fillna(method='ffill')
print('Sample for winter 1984 = ',df[df.Season=='Winter_1984'].Sample.sum())

编辑3:

下面是完整的示例,如果您在同一个月有几行:

#### Build our df
#### This is just to make it clear that we will have 2 rows of each month. It could be more or less.
dates = pd.date_range("1983-09-01","1985-12-31",freq="1M")
dates2 = pd.date_range("1983-09-01","1985-12-31",freq="1M")
df1 = pd.DataFrame(np.random.randint(100, 200,size=28)/100,index =dates,columns=["Sample"]).append(pd.DataFrame(np.random.randint(100, 200,size=28)/100,index =dates2,columns=["Sample"]))
df1 = df1.sort_index()
#### Now, to keep it clear, even if we could do faster, let's do a dataframe with 1 row per month with total of sample each time
df = pd.DataFrame()
df = df1.groupby(df1.index).sum()
#### Let's sort by date to be sure that it won't me messy
#### If you've got a 'Date' column and not the index, apply a .sort_values('Date') instead of sort_index
df = df.sort_index()
#### If youve got a 'Date' column, it will be df.Date.dt.month istead of df.index.month
_condition_winter = (df.index.month>=1)&(df.index.month<=3)
_condtion_spring = (df.index.month>=4)&(df.index.month<=6)
_condition_summer = (df.index.month>=7)&(df.index.month<=9)
_condition_automn = (df.index.month>=10)@(df.index.month<=12)
df['Season'] = np.where(_condition_winter,'Winter',np.where(_condtion_spring,'Spring',np.where(_condition_summer,'Summer',np.where(_condition_automn,'Automn',np.nan))))
df['Season'] = df['Season']+'_'+df.index.strftime(date_format='%Y')
df['Season'] = df['Season'].shift(-1).fillna(method='ffill')
print('Sample for winter 1984 = ',df[df.Season=='Winter_1984'].Sample.sum())

我认为您应该创建一个lambda函数,该函数根据月份和日期的值选择正确的季节。

def seasons(date):
m = date.month
d = date.day
season=None
if (3==m and d>=21) or m==4 or m==5 or (m==6 and 20<=d):
season = 'spring'
elif (6==m and d>=21 ) or m==7 or m==8 or (m==9 and 20<=d):
season = 'sommer'
elif (9==m and d>=21 ) or m==10 or m==11 or (m==12 and 20<=d):
season = 'autumn'
elif (12==m and d>=21 ) or m==1 or m==2 or (m==3 and 20<=d):
season = 'winter'
return season
df['season'] = df.apply(lambda x: seasons(x['date']), axis=1)

请注意,季节也是按天选择的。因为冬季的定义是从12月21日到3月20日,以此类推。

我找到了另一种绕过方法。所以我想把它放在这里。

  1. 1个月后所有样品的移位
  2. 按月附加季节
  3. 然后你可以用任何你想要的方式处理样品。例如

如果你把它编码成这样:

from dateutil.relativedelta import *

df.loc[:, 'shift_time'] = df.apply(lambda x: x['real_datetime'] + relativedelta(months=+1), axis=1)
df.loc[:, 'season'] = df['shift_time'].dt.quarter
grouped = df.groupby([(df['shift_time'].dt.year), (df['season'])]).count()

最新更新