如何在熊猫中将日历年转换为水年
Posted
技术标签:
【中文标题】如何在熊猫中将日历年转换为水年【英文标题】:How to convert calendar year to water year in pandas 【发布时间】:2019-02-05 22:00:08 【问题描述】:这个问题已经用 R 解决了,但是我还没有看到 Python 有用的例子。我想了解如何将日历年(1990 年 1 月 1 日至 2010 年 12 月 31 日)排放数据转换为水年数据(即 1990 年 1 月 1 日至 2010 年 9 月 31 日)。感谢您的帮助。
【问题讨论】:
df['date'] = df['date'] + pd.DateOffset(months=9)
【参考方案1】:
使用来自USGS 03335500 WABASH RIVER AT LAFAYETTE, IN的数据
日期:2001-10-01 - 2017-09-31'datetime'
列必须设置为datetime
dtype
,通过使用parse_dates
导入数据,或在导入数据后使用pd.to_datetime()
。
使用pandas.Series.where
确定水年。
.dt
accessor 提取month
和year
数字。
如果月份数小于10,则水年为.dt.year
,否则,水年为.dt.year + 1
对于此 DataFrame 中的 282757
行,比来自此 answer 的 .apply
函数快 13 倍。
import pandas as pd
# Load the data
df = pd.read_csv('WabashRiver_Flow.csv', parse_dates=['datetime'])
# drop na values
df = df.dropna()
# determine the water year
df['water_year'] = df.datetime.dt.year.where(df.datetime.dt.month < 10, df.datetime.dt.year + 1)
# display(df.head())
agency_cd site_no datetime tz_cd discharge_cfps water_year
0 USGS 3335500 2001-10-01 00:00:00 EST 2610 2002
1 USGS 3335500 2001-10-01 01:00:00 EST 2610 2002
2 USGS 3335500 2001-10-01 02:00:00 EST 2610 2002
3 USGS 3335500 2001-10-01 03:00:00 EST 2630 2002
4 USGS 3335500 2001-10-01 04:00:00 EST 2630 2002
按水年计算平均流量
annual_mean_discharge_rate = df.groupby('water_year')[['discharge_cfps']].mean()
# display(annual_mean_discharge_rate)
discharge_cfps
water_year
2002 9379.829589
2003 8678.468324
2004 8562.505005
2005 8928.776256
2006 6710.805312
2007 10331.564789
2008 10626.336623
2009 8972.046607
2010 5298.569557
2011 10519.540869
2012 9013.624424
2013 9007.924205
2014 9079.561658
2015 12267.393776
2016 6445.875810
2017 10240.721464
annual_mean_discharge_rate.plot.bar(figsize=(8, 6), xlabel='Water Year', ylabel='Discharge (cubic feet / sec)', legend=False)
%%timeit
比较
pandas.Series.where
与 pandas.Series.apply
和 np.where
相比,以及来自另一个答案的功能。
.Series.where
是矢量化的,而 .apply
不是。
import numpy as np
# function from other answer; updated because pd.datetime is deprecated
def assign_wy(row):
if row.month>=10:
return(row.year + 1)
else:
return(row.year)
%%timeit
df.datetime.dt.year.where(df.datetime.dt.month < 10, df.datetime.dt.year + 1)
[out]:
66.9 ms ± 1.67 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
%%timeit
df.datetime.apply(lambda v: np.where(v.month >= 10, v.year + 1, v.year))
[out]:
1.38 s ± 23 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%%timeit
df.datetime.apply(lambda x: assign_wy(x))
[out]:
861 ms ± 9.3 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
【讨论】:
【参考方案2】:您可以使用apply 并编写自己的函数来创建一个新列WY
:
如果你有df
:
Date Discharge
0 2011-10-01 00:00:00 0.0
1 2011-10-01 01:00:00 0.0
2 2011-10-01 02:00:00 0.0
3 2011-10-01 03:00:00 0.0
4 2011-10-01 04:00:00 0.0
然后:
import pandas as pd
def assign_wy(row):
if row.Date.month>=10:
return(pd.datetime(row.Date.year+1,1,1).year)
else:
return(pd.datetime(row.Date.year,1,1).year)
df['WY'] = df.apply(lambda x: assign_wy(x), axis=1)
【讨论】:
以上是关于如何在熊猫中将日历年转换为水年的主要内容,如果未能解决你的问题,请参考以下文章