【问题标题】:How to eliminate leap years in pandas data frame如何消除熊猫数据框中的闰年
【发布时间】:2021-12-18 23:54:24
【问题描述】:

我有 1901-1940 年的每日温度数据。我想排除闰年,即删除任何落在 2/29 的温度数据。我的数据目前是一个长数组。我正在重塑它,使每一年都是一行,每一列都是一天。我正在尝试使用此处的最后一行代码删除闰年:

import requests
from datetime import date
params = {"sid": "PHLthr", "sdate":"1900-12-31", "edate":"2020-12-31", "elems": [{"name": "maxt", "interval": "dly",  "duration": "dly", "prec": 6}]}
baseurl = "http://data.rcc-acis.org/StnData"
#get the data
resp = requests.post(baseurl, json=params)
#package into the dataframe
df = pd.DataFrame(columns=['date', 'tmax'], data=resp.json()['data'])
#convert the date column to datetimes
df['date']=pd.to_datetime(df['date'])
#select years
mask = (df['date'] >= '1900-01-01') & (df['date'] <= '1940-12-31')
Baseline=df.loc[mask]
#get rid of leap years:
Baseline=Baseline.loc[(Baseline['date'].dt.day!=29) & (Baseline['date'].dt.month!=2)]

但是当我重塑数组时,我注意到有 366 列而不是 365 列,所以我认为我实际上并没有摆脱 2 月 29 日的数据。我将如何完全消除在整个数据集中记录在 2/29 上的任何温度数据。我只想要每年 365 个数据点。

daily=pd.DataFrame(data={'date':Baseline.date,'tmax':Baseline.tmax})
daily['day']=daily.date.dt.dayofyear
daily['year']=daily.date.dt.year
daily.pivot(index='year', columns='day', values='tmax')

【问题讨论】:

标签: python pandas dataframe datetime weather


【解决方案1】:

问题的根源在于您使用了daily.date.dt.dayofyear

一年中的每一天,包括2 月 29 日 都有自己的编号。

让事情变得更糟,例如3 月 1 日dayofyear

  • 61 闰年,
  • 非闰年为 60。

一种可能的解决方案是将 day 列设置为字符串 月和日的表示。 为了在透视表中提供正确的排序,月份部分应该放在第一位。

因此,在将 date 列转换为 datetime 后,创建两者 额外的列运行:

daily['year'] = daily.date.dt.year
daily['day'] = daily.date.dt.strftime('%m-%d')

然后就可以过滤掉Feb 29,一次性生成数据透视表:

result = daily[daily.day != '02-29'].pivot(index='year', columns='day',
    values='tmax')

对于一些有限的源数据样本,除了你的,我得到了:

day   02-27  02-28  03-01  03-02
year                            
2020     11     10     14     15
2021     11     21     22     24

另一种选择

创建 3 个额外的列:

daily['year']  = daily.date.dt.year
daily['month'] = daily.date.dt.strftime('%m')
daily['day']   = daily.date.dt.strftime('%d')

注意月和日的字符串表示,保持领先 零。

然后过滤掉 Feb 29 并生成带有 MulitiIndex 的数据透视表 在列上:

result = daily[(daily.month != '02') | (daily.day != '29')].pivot(
    index='year', columns=['month', 'day'], values='tmax')

这次的结果是:

month  02      03    
day    27  28  01  02
year                 
2020   11  10  14  15
2021   11  21  22  24

【讨论】:

    【解决方案2】:

    简单的方法是在构建数组之前消除这些项目。

    import requests
    from datetime import date
    
    params = {"sid": "PHLthr", "sdate":"1900-12-31", "edate":"2020-12-31", "elems": [{"name": "maxt", "interval": "dly",  "duration": "dly", "prec": 6}]}
    baseurl = "http://data.rcc-acis.org/StnData"
    #get the data
    resp = requests.post(baseurl, json=params)
    vals = resp.json()
    rows = [row for row in vals['data'] if '02-29' not in row[0]]
    print(rows)
    

    【讨论】:

    • 这并不能解决 OP 的问题。他们想在daily["day"]中“跳过”编号为“02-29”的人
    【解决方案3】:

    由于使用了dayofyear,您将获得 366 列。这将根据实际日历计算日期(即不删除 2 月 29 日)。

    看到这个:

    >>> daily.iloc[1154:1157]
    
               date       tmax  day  year
    1154 1904-02-28  38.000000   59  1904
    1156 1904-03-01  39.000000   61  1904
    1157 1904-03-02  37.000000   62  1904
    

    注意这一天从 59 日变为 61 日(第 60 天是 1904 年 2 月 29 日)。

    【讨论】:

      猜你喜欢
      • 2016-04-30
      • 1970-01-01
      • 2016-08-14
      • 1970-01-01
      • 2020-07-21
      • 2019-01-06
      • 1970-01-01
      • 2017-05-28
      • 1970-01-01
      相关资源
      最近更新 更多