Skip to main content
 首页 » 编程设计

python之计算 Pandas 数据框中的年数

2025年05月04日13shihaiming

我编写了一个困惑的函数,它根据数据帧的长度计算数据帧中的年数(假设数据帧具有一年中每一天的值)。

它工作正常,但它有很多代码可以变得更智能(但我不确定如何...)

这是函数,它只有 10 年,我希望它适用于任何大小的数据集。我可以通过复制和粘贴并进一步将总数相加来进一步扩展它,但是必须有一种更聪明的方法来编写这段代码。

def numyears(x): 
    if len(x.index) <= 366: 
        return 1 
    elif len(x.index) <= 732: 
        return 2 
    elif len(x.index) <= 1098: 
        return 3 
    elif len(x.index) <= 1464: 
        return 4 
    elif len(x.index) <= 1830: 
        return 5 
    elif len(x.index) <= 2196: 
        return 6 
    elif len(x.index) <= 2562: 
        return 7 
    elif len(x.index) <= 2928: 
        return 8 
    elif len(x.index) <= 3294: 
        return 9 
    elif len(x.index) <= 3660: 
        return 10 
    else:  
        return 'ERROR' 

请您参考如下方法:

只访问 year 属性然后只获取唯一值的 len 似乎更合理:

In [2]: 
s = pd.date_range(dt.datetime(1900,1,1), end=dt.datetime(2000,1,1), freq='6M') 
s 
 
Out[2]: 
DatetimeIndex(['1900-01-31', '1900-07-31', '1901-01-31', '1901-07-31', 
               '1902-01-31', '1902-07-31', '1903-01-31', '1903-07-31', 
               '1904-01-31', '1904-07-31', 
               ... 
               '1995-01-31', '1995-07-31', '1996-01-31', '1996-07-31', 
               '1997-01-31', '1997-07-31', '1998-01-31', '1998-07-31', 
               '1999-01-31', '1999-07-31'], 
              dtype='datetime64[ns]', length=200, freq='6M') 
 
In [8]: 
len(np.unique(s.year)) 
 
Out[8]: 
100 

通过这种方式,它可以处理不常见的周期、缺失的日期、与年份边界重叠的条目等。

您还可以将索引转换为 Series 并调用 nunique:

In [11]: 
s.to_series().dt.year.nunique() 
 
Out[11]: 
100 

鉴于您已经将 datetime 作为列,那么这将起作用:

df['date_col'].dt.year.nunique() 

如有必要,您可以使用以下方法转换为日期时间:

df['date_col'] = pd.to_datetime(df['date_col']) 

更新

所以您的要求似乎是计算完整的年份,如果您将索引设置为年份和日期部分,那么您可以在年份级别进行计数,然后过滤不 >= 365 的行以获得完整年份:

In [34]: 
df = pd.DataFrame({'date':pd.date_range(dt.datetime(1900,6,1), end=dt.datetime(1910,6,1))}) 
count = df.set_index([df['date'].dt.year, df['date'].dt.day]).count(level=0) 
count 
 
Out[34]: 
      date 
date       
1900   214 
1901   365 
1902   365 
1903   365 
1904   366 
1905   365 
1906   365 
1907   365 
1908   366 
1909   365 
1910   152 
 
In [39]: 
len(count[count >= 365].dropna()) 
 
Out[39]: 
9