作为单个代码块
没有循环,没有 lambda 函数。非常快(从 1990 年到 2022 年 1 月 1 日,11,688 行约 90 毫秒)。
df = df.assign(
date=pd.to_datetime(df[['day', 'month', 'year']])
).set_index('date')[['Temperature']]
by_month = pd.Grouper(freq='M')
df = df.assign(
temp_sorted=df.groupby(by_month)['Temperature'].transform(sorted)
)
df = df.assign(
CDF_temp=df.groupby(by_month)['temp_sorted'].agg('rank', pct=True)
)
解释(一点一点)
如果您首先将列 day, month, year 合并为一个 date 并使其成为索引,这会更容易。
仅使用您提供的四行作为示例数据:
df = pd.DataFrame({
'day': [1, 1, 31, 31],
'month': [1, 1, 12, 12],
'year': [2010, 2011, 2010, 2011],
'Temperature': [269.798567, 274.085177, 273.610214, 274.855967],
})
df = df.assign(
date=pd.to_datetime(df[['day', 'month', 'year']])
).set_index('date')[['Temperature']]
>>> df
Temperature
date
2010-01-01 269.798567
2011-01-01 274.085177
2010-12-31 273.610214
2011-12-31 274.855967
现在,您可以非常轻松地按月分组。例如,计算每个月的平均温度:
>>> df.groupby(pd.Grouper(freq='M')).mean()
Temperature
date
2010-01-31 269.798567
2010-02-28 NaN
...
2010-11-30 NaN
2010-12-31 273.610214
2011-01-31 274.085177
2011-02-28 NaN
...
2011-11-30 NaN
2011-12-31 274.855967
现在,对于您问题的第二部分:如何重新排序当月的温度,并计算它的 CDF。我们先生成随机数据进行测试:
np.random.seed(0) # reproducible values
ix = pd.date_range('2010', '2012', freq='D', closed='left')
df = pd.DataFrame(
np.random.normal(270, size=len(ix)),
columns=['Temperature'], index=ix)
>>> df
Temperature
2010-01-01 271.764052
2010-01-02 270.400157
2010-01-03 270.978738
2010-01-04 272.240893
2010-01-05 271.867558
... ...
2011-12-27 269.112819
2011-12-28 269.067211
2011-12-29 271.243319
2011-12-30 270.812674
2011-12-31 270.587259
[730 rows x 1 columns]
对每个月内的温度进行排序:
by_month = pd.Grouper(freq='M')
df = df.assign(
temp_sorted=df.groupby(by_month)['Temperature'].transform(sorted)
)
注意:虽然使用上述值,看起来温度已在全球范围内重新排序,但事实并非如此。它们仅在每个月内重新订购。例如:
>>> df['2010-01-30':'2010-02-02']
Temperature temp_sorted
2010-01-30 271.469359 272.240893
2010-01-31 270.154947 272.269755
2010-02-01 270.378163 268.019204
2010-02-02 269.112214 268.293730
最后,计算每个月的 CDF:
df = df.assign(
CDF_temp=df.groupby(by_month)['temp_sorted'].agg('rank', pct=True)
)
我们得到:
>>> df
Temperature temp_sorted CDF_temp
2010-01-01 271.764052 267.447010 0.032258
2010-01-02 270.400157 268.545634 0.064516
2010-01-03 270.978738 269.022722 0.096774
2010-01-04 272.240893 269.145904 0.129032
2010-01-05 271.867558 269.257835 0.161290
... ... ... ...
2011-12-27 269.112819 271.094638 0.870968
2011-12-28 269.067211 271.243319 0.903226
2011-12-29 271.243319 271.265078 0.935484
2011-12-30 270.812674 271.327783 0.967742
2011-12-31 270.587259 272.132153 1.000000