如何消除 pandas 数据框中的闰年
How to eliminate leap years in pandas data frame
我有 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')
简单的方法是在构建数组之前消除这些项目。
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)
由于使用 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 日)。
你问题的根源是你使用了daily.date.dt.dayofyear.
一年中的每一天,包括 2 月 29 日 都有自己的编号。
更糟的是,例如3 月 1 日 有 dayofyear:
- 闰年61,
- 平年60。
可能的解决方案之一是将 day 列设置为字符串
月份和日期的表示。
要在旋转 table 中提供正确的排序,月份部分应该放在第一位。
因此,在将 date 列转换为 datetime 之后,创建两者
附加列 运行:
daily['year'] = daily.date.dt.year
daily['day'] = daily.date.dt.strftime('%m-%d')
然后就可以过滤掉Feb 29,一次性生成枢轴table:
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 并使用 MultiiIndex 生成枢轴 table
在列上:
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
我有 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')
简单的方法是在构建数组之前消除这些项目。
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)
由于使用 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 日)。
你问题的根源是你使用了daily.date.dt.dayofyear.
一年中的每一天,包括 2 月 29 日 都有自己的编号。
更糟的是,例如3 月 1 日 有 dayofyear:
- 闰年61,
- 平年60。
可能的解决方案之一是将 day 列设置为字符串 月份和日期的表示。 要在旋转 table 中提供正确的排序,月份部分应该放在第一位。
因此,在将 date 列转换为 datetime 之后,创建两者 附加列 运行:
daily['year'] = daily.date.dt.year
daily['day'] = daily.date.dt.strftime('%m-%d')
然后就可以过滤掉Feb 29,一次性生成枢轴table:
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 并使用 MultiiIndex 生成枢轴 table 在列上:
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