【问题标题】:Run function for each month of the year within a dataframe在数据框中为一年中的每个月运行函数
【发布时间】:2023-03-16 12:05:01
【问题描述】:

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

我怀疑我将不得不循环这个。但我不知道怎么做。

【问题讨论】:

    标签: python dataframe loops


    【解决方案1】:

    作为单个代码块

    没有循环,没有 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
    

    【讨论】:

      猜你喜欢
      • 2021-08-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-27
      • 2019-07-18
      • 1970-01-01
      相关资源
      最近更新 更多