【问题标题】:Taking percentile in Python along 3rd dimension在 Python 中沿第三维取百分位数
【发布时间】:2021-07-06 07:41:40
【问题描述】:

我一直在努力解决这个问题。我有一个 55115 x 34 的矩阵,其中第一个维度上的每个数字是一天,151 年,总共 55115 个点。

我正在尝试获取第一个维度中值的每月百分位数,因此我首先添加了一个日期列,随后将其分组为月份,尽管我无法找出获取百分位数(第 95 个)的最佳方法天数和三维(这里是 34)。所以在对月份进行分组之后,矩阵应该是 151 x 12 x 34,我想沿着第三维取第 95 个百分位数,所以理论上我的最终矩阵应该是 151 x 12。以下是我迄今为止将日期添加到数组中的内容:

dates = pd.date_range(start='1950-01-01', end='2100-12-31', freq='D') #create daily date range from 1950 to 2100

leap = [] #empty array
for each in dates:
    if each.month==2 and each.day ==29: #find each leap day (feb 29)
        leap.append(each)

dates = dates.drop(leap) #get rid of leap days
dates = pd.to_datetime(dates) #convert to datetime format 
data = {'wind': winddata, 'time': dates} #create table with both dates and data
df = pd.DataFrame(data) #create dataframe
df.set_index('time') #index time
df.groupby(df['time'].dt.strftime('%b'))['wind'].sort_values()

这就是我必须采用的百分位数:

months = df.groupby(pd.Grouper(key='time',freq = "M")) #group each month
monthly_percentile = months.aggregate(lambda x: np.percentile(x, q = 95)) #percentile across each month 

虽然,这似乎不起作用。我对其他方法持开放态度,我只是希望 a) 将 55115 x 34 数据集重新排列为月,使其为 151(年)x 365(天)x 34(集合),然后百分位数跨越月份和三维,所以我最终得到 151 x 12 的总数。如果我没有详细说明,我很乐意澄清任何事情。任何详细的回复都会非常有帮助。提前非常感谢您!

【问题讨论】:

    标签: python pandas numpy time statistics


    【解决方案1】:

    如果我的问题正确,我能想到的最直接的解决方案是添加列 yearmonth,然后对它们进行分组并计算所需的百分位数:

    import pandas as pd
    import numpy as np
    
    dates = pd.date_range(start='1950-01-01', end='2100-12-31', freq='D')
    dates_months = [date.month for date in dates]
    dates_years = [date.year for date in dates]
    values = np.random.rand(34, len(dates))
    df = pd.DataFrame()
    
    df['date'] = dates
    df['year'] = dates_years
    df['month'] = dates_months
    for i in range(34):
        df[f'values_{i}'] = values[i]
    
    df = df.melt(id_vars=['date', 'year', 'month'], value_vars=[f'values_{i}' for i in range(34)])
    sub = df.groupby(['year', 'month']).value.apply(lambda x: np.quantile(x, .95)).reset_index()
    

    最后,如果你真的需要一个 151 x 12 数组而不是长度为 1812 (=151*12) 的年月百分比表,你可以使用这样的东西:

    crosstab = pd.crosstab(index=sub['year'], columns=sub['month'], values=sub['values'], aggfunc=lambda x: x)
    

    【讨论】:

    • 非常感谢您的回复!这似乎适用于 55115 x 1,但似乎不适用于 55115 x 34。你知道我如何将它应用于所有 34 个“运行”,这样我最终还是会得到 1812 x 1 吗?非常感谢您的帮助。
    • 对于其他上下文,我使用的模型每天输出 34 次不同的数据(这 34 次中的每一次都略有不同)。因此,不知何故,如果我可以将日期列应用于所有 34 次运行,但只取一次百分位(我不想取月份的百分位,然后取 34 次的百分位,我认为这在统计上是错误的)。再次感谢您!
    • 我修改了答案,基本上你需要的是添加一个melt
    • 非常感谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-24
    • 2018-06-29
    • 2013-07-27
    • 1970-01-01
    • 1970-01-01
    • 2019-04-02
    相关资源
    最近更新 更多