拨开荷叶行,寻梦已然成。仙女莲花里,翩翩白鹭情。
IMG-LOGO
主页 文章列表 在资料框中为一年中的每个月运行函式

在资料框中为一年中的每个月运行函式

白鹭 - 2022-03-08 1980 0 0

我在 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 评论

发表评论

您的电子邮件地址不会被公开。 必填的字段已做标记 *