python - groupby 多索引生成 excel 数据透视表结果,解决方案太难看
问题描述
我正在分析带有日期和温度的气候数据,1950-2000 之间的每一天都有一个平均温度。我的目的是计算 1950-2000 年 50 年中最热的 10 个年份,并可视化在 1950-2000 年的 5 个十年中分别有多少年。我认为,具有多索引(0 级:十年,1 级:年)的 groupby 将是正确的方法。我曾期望返回 50 年(df 的长度),其中 5 个十年作为相应的 0 级索引。但相反,我得到 250 行(5 个十年 x 50 年)。这不是我想要的,也不是我需要的,因为分组数据框的十年 1950 包括所有其他十年的年份,但温度为零,其他几十年也一样 为什么 groupby 会这样做,我怎样才能获得 50 年的长度?我可以在 excel 中创建它,以几十年和几年为行,以平均温度为值:
希望你明白我的意思,下面是一个示例代码,我希望有助于重现问题。
一个(坏的)解决方案是从结果系列中删除所有值为零的行,但是如果一行的平均值实际上是 0,这既不优雅也不好:grouped = grouped[grouped != 0]
谢谢!
# import libraries
import pandas as pd
import numpy as np
import datetime
from numpy.random import randint
# create dataframe with dates as index and temperature on each date as column
cols = ['temperature']
dates = np.arange('1950', '2000', dtype='datetime64[D]')
len_dates = len(dates)
temp = randint(40, size=len_dates)
df = pd.DataFrame(temp, index=dates, columns=cols)
# extract year
df['year'] = df.index.year.astype('category')
# bin years into decades
cut_bins = np.arange(1950,2010,10).tolist()
cut_labels = [year for year in range(1950, 2000,10)]
df['decade'] = pd.cut(df['year'], bins=cut_bins, labels=cut_labels, include_lowest=True).astype('category')
df.head()
# groupby
grouped = df.groupby(['decade','year'])['temperature'].mean()
print('len(df): ', len(df))
print('len(grouped): ', len(grouped))
print('len(decade): ', len(df['decade'].unique()))
print('len(years): ', len(df['year'].unique()))
# resulting object has 250 rows yet only 50 years
print(grouped)
# remove needless rows from series
print(grouped = grouped[grouped != 0])
df.to_excel('groupedtest.xlsx')
解决方案
好吧,您要求 pandas 对包括十年/年在内的所有可能组求和,因此 pandas 将应用所有可能性的笛卡尔积(5 x 50 = 250)。
我相信您上面所做的大部分是正确的,唯一缺少的步骤就是对输出进行排序。这是我对这项任务的看法。
import pandas as pd
import numpy as np
import datetime
from numpy.random import randint
# create dataframe with dates as index and temperature on each date as column
cols = ['temperature']
dates = np.arange('1950', '2000', dtype='datetime64[D]')
len_dates = len(dates)
temp = randint(40, size=len_dates)
df = pd.DataFrame(temp, index=dates, columns=cols)
# extract year
df['year'] = df.index.year
idx = (
df
.groupby(["year"], as_index = False) # group just by year
.sum() # find temp for the year, which from the question should be the sum
.assign(
decade = lambda df: df["year"].mod(100) - df["year"].mod(10)
) # compute the decade after grouping
.sort_values("temperature", ascending = False) # sort by highest temp
.set_index("decade")
.head(10) # get top 10
.index
)
获得前 10 名后,您可以使用计数器。
from collections import Counter
Counter(idx)
推荐阅读
- c# - 在 AZURE 服务器上托管的站点的文件下载失败
- javascript - 在 TypeScript 中导出多个变量以赋予 CommonJS 等效项
- javascript - 如何将动态值传递给jquery验证函数
- java - 将用户发送到应用程序。如果 App 不存在发送到 playstore
- json - Oracle 12c PL/JSON 在 5000 个字符处截断字符串
- unit-testing - 带有 test-utils 的 vue.js 测试单元未通过
- ruby-on-rails - 在 Rails 中默认使用 postgres
- r - r中的行随机抽样
- java - 使用扫描仪进行嵌套方法测试
- r - 计数同时满足这两个条件的 ID