我在 Pandas 中有一个 DataFrame,它有 2010 年和 2011 年每个月的每日温度值:
> day month year Temperature
> 1 1 2010 269.798567
> 1 1 2011 274.085177
> ....
> 31 12 2010 273.610214
> 31 12 2011 274.855967
> [730 rows x 4 columns]
我想将一年中每个月的温度从最低到最高排序。然后计算每个月和每年的累积分布函式(cdf)。
我设法用过滤器做到了这一点,只查看一个特定的月份和特定的年份。现在我正在努力在所有月份和年份中应用此代码。我的代码看起来像这样:
month = 1
year = 2010
filt = (df['month'] == month) & (df['year'] == year)
dfMonth = df.loc[filt]
#Sort temperature from least to greatest
SortDF = dfMonth.sort_values(variable,ascending=True)
# calculate cdf
NumberOfDays = len(SortDF)
EmptyList = list(range(1, NumberOfDays 1))
CDF = [((element -0.5)/NumberOfDays)for element in EmptyList if element < NumberOfDays]
CDF.append(1)
# Add CDF values into Dataframe as new column
SortDF['CDF' '_' Temperature ] = CDF
最后得到:
day month year Temperature CDF_Temperature
25 1 2010 259.990152 0.016129
24 1 2010 260.644554 0.048387
....
28 1 2010 272.642832 0.951613
10 1 2010 273.004253 1.000000
我怀疑我将不得不回圈这个。但我不知道如何。
uj5u.com热心网友回复:
作为单个代码块
没有回圈,没有 lambda 函式。非常快(从 1990 年到 2022-01-01 的 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
0 评论