熊猫:查找发生年度事件的平均月/日

时间:2019-07-22 04:41:35

标签: python pandas datetime

我有一个包含两个时间列的Pandas df。这些列包含年度事件的yyyy-mm-dd。

如何计算所有年份事件发生的平均mm-dd?

我想这涉及计数(每行)实际日期和一年中1月1日之间的天数,但是我看不到如何有效地使用Pandas。

谢谢!

MapShapeSelectionBehavior

编辑: 完成重现错误的步骤:

    dormancy1   greenup1    maturity1   senescence1 dormancy2   greenup2    maturity2   senescence2
8   2002-08-31  2002-04-27  2002-05-06  2002-08-21  NaT NaT NaT NaT
22  2003-09-17  2003-06-06  2003-06-15  2003-07-22  NaT NaT NaT NaT
36  2004-09-10  2004-04-20  2004-05-15  2004-05-24  NaT NaT NaT NaT
44  2005-08-13  2005-04-24  2005-06-29  2005-07-18  NaT NaT NaT NaT
74  2007-05-10  2007-03-13  2007-04-07  2007-05-01  NaT NaT NaT NaT
95  2009-09-18  2009-04-26  2009-05-06  2009-06-03  NaT NaT NaT NaT
113 2010-09-09  2010-05-29  2010-06-08  2010-07-19  NaT NaT NaT NaT

3 个答案:

答案 0 :(得分:0)

这就是我要做的:

将数据转换为日期时间格式(如果尚未完成的话):

df['dormancy1'] = pd.to_datetime(df['dormancy1'])
df['greenup1'] = pd.to_datetime(df['greenup1'])

获取该行年份的1月1日(我假设您的事件在同一年发生):

df['1Jyear'] = df['dormancy1'].dt.year.apply(lambda x: dt.datetime(x, 1, 1))

这是您的数据框现在的外观:

df.head()
     dormancy1    greenup1      1Jyear
0   2002-08-31  2002-04-27  2002-01-01
1   2003-09-17  2003-06-06  2003-01-01
2   2004-09-10  2004-04-20  2004-01-01
3   2005-08-13  2005-04-24  2005-01-01
4   2007-05-10  2007-03-13  2007-01-01

要获取每个事件的平均月份和日期:

df[['dormancy1', 'greenup1']].apply(lambda x: pd.to_datetime((x - df['1Jyear']).values.astype(np.int64).mean()).strftime('%m-%d'))

这将输出以下系列:

dormancy1    08-10
greenup1     04-30

让我知道这是否是必需的结果,希望对您有帮助。

更新:处理丢失的数据

我正在处理以下数据:

     dormancy1  greenup1
0   2002-08-31  2002-04-27
1   2003-09-17  NaN
2   2004-09-10  2004-04-20
3   2005-08-13  2005-04-24
4   NaN 2007-03-13
5   2009-09-18  2009-04-26
6   2010-09-09  2010-05-29
7   2012-05-30  2012-05-04
8   NaN NaN

要计算每一行的年份(我得到在列中找到的第一年,因此我再次假设每个事件的年份都相同,但是如果不一致,则需要为每个事件计算不同的列事件):

def computeYear(row):
    for i in row:
        if pd.isna(i):
            pass
        else:
            return dt.datetime(int(i.strftime('%Y')), 1, 1)
    return np.nan
df['1Jyear'] = df[['dormancy1', 'greenup1']].apply(lambda row: computeYear(row), axis=1)

要获取结果(与以前相同):

df[['dormancy1', 'greenup1']].apply(lambda x: pd.to_datetime((x - df['1Jyear']).values.astype(np.int64).mean()).strftime('%m-%d'))

输出:

dormancy1    07-20
greenup1     04-17
dtype: object

答案 1 :(得分:0)

好的,现在您要在这里使用的是旧的 pandas.Series.dt.dayofyear 函数。这将告诉您特定日期一年中发生了多少天。这可能使您脑海中扫了一下,现在就在建立答案,但以防万一:

avg_day_dormancy1 = df['dormancy1'].dt.dayofyear.mean()

# Now let's add those days to a year to get an actual date
import datetime as dtt  # You could do this in pandas, but this is quick and dirty
avg_date_dormancy1 = dtt.datetime.strptime('2000-01-01', '%Y-%m-%d')  # E.g. get date in year 2000
avg_date_dormancy += dtt.timedelta(days=avg_day_dormancy1)

鉴于您提供的数据,我将dormancy1的平均发生日期定为8月10日。例如,您也可以在.std()系列上调用dayofyear方法,并获得发生这些事件的95%置信区间。

答案 2 :(得分:0)

这是另一种方式。希望这会有所帮助

import pandas as pd
from datetime import datetime

计算这两个事件的平均一天时间

mean_greenup_DoY = df['greenup1'].apply(lambda x: datetime.strptime(x, '%Y-%m-%d').timetuple().tm_yday).mean()
mean_dormancy_DoY = df['dormancy1'].apply(lambda x: datetime.strptime(x, '%Y-%m-%d').timetuple().tm_yday).mean()

此方法首先将日期字符串转换为datetime对象,然后使用lambda函数中的逻辑查找一年中的某天,这意味着平均值()用于获取一年中的平均天。