首页 > 解决方案 > 使用时间间隔创建一个将产生数据帧的函数

问题描述

假设我有一个df,回忆

Number_of_photos
1990 27
1991年 21
1992 39
1993 22
1994 10
1995 12
1996 22
1997 22
1998 40
1999 27
2000 18
2001年 20
2002年 18
2003年 14
2004年 33
2005年 10
2006年 24
2015 17

我想创建一个函数,它将吐出一个数据框,用户将在其中输入开始年份和一个整数,该整数将确定时间范围(即,如果开始年份 = 1998 和 int = 4,那么时间范围将是 1998-2001、2002-2005、2006-2009、2010-2013 和 2014-2017年)。在这些时间范围内,该函数将生成最大 Number_of_photos(即 1998-2001 将生成 40,2002-2005 将生成 33,2006-2009 将生成 24,2010-2013 将生成“无”,最后 2014-2017 将生成 17 )。

关于如何定义将生成数据框的函数的任何想法?

[In]  def max_photos(df,start,integer):



[Out] |Timeframe|Max_Year|Max_Num_Photos| 
      |---------|--------|--------------|
      |1998-2001|  1998  |      40      | 
      |2002-2005|  2004  |      33      | 
      |2006-2009|  2006  |      24      | 
      |2010-2013|  None  |     None     | 
      |2014-2017|  2015  |      17      | 

标签: pythonpython-3.xpandasdataframerange

解决方案


cut与聚合max和一起使用Series.idxmax,最后添加缺少的类别添加DataFrame.reindex

def max_photos(df,start,integer):
    df = df[df['Year'] >= start].copy()
    bins = range(start, df.Year.max() + integer, integer)
    labels = [f'{i}-{j-1}' for i, j in zip(bins[:-1], bins[1:])]
    df['g'] = pd.cut(df['Year'],bins=bins,labels=labels,include_lowest=True,right=False) 


    return (df.set_index('Year')
              .groupby('g', observed=True)
              .agg(Max_Year=('Number_of_photos','idxmax'),
                   Max_Num_Photos=('Number_of_photos','max'))
              .reindex(df['g'].cat.categories.unique())
              .rename_axis('Timeframe')
              .reset_index())

print (max_photos(df, 1998, 4))
   Timeframe  Max_Year  Max_Num_Photos
0  1998-2001    1998.0            40.0
1  2002-2005    2004.0            33.0
2  2006-2009    2006.0            24.0
3  2010-2013       NaN             NaN
4  2014-2017    2015.0            17.0

编辑:这是Location每个最大值追加新列的解决方案Max_Num_Photos- 首先添加到索引中DataFrame.set_index,最后从元组创建新列DataFrame.assign

#sample data
df['Location'] = 'loc' + df.index.astype(str)
print (df)
    Year  Number_of_photos Location
0   1990                27     loc0
1   1991                21     loc1
2   1992                39     loc2
3   1993                22     loc3
4   1994                10     loc4
5   1995                12     loc5
6   1996                22     loc6
7   1997                22     loc7
8   1998                40     loc8
9   1999                27     loc9
10  2000                18    loc10
11  2001                20    loc11
12  2002                18    loc12
13  2003                14    loc13
14  2004                33    loc14
15  2005                10    loc15
16  2006                24    loc16
17  2015                17    loc17

def max_photos(df,start,integer):
    df = df[df['Year'] >= start].copy()
    bins = range(start, df.Year.max() + integer, integer)
    labels = [f'{i}-{j-1}' for i, j in zip(bins[:-1], bins[1:])]
    df['g'] = pd.cut(df['Year'],bins=bins,labels=labels,include_lowest=True,right=False) 


    return (df.set_index(['Year','Location'])
              .groupby('g', observed=True)
              .agg(Max_Year=('Number_of_photos','idxmax'),
                   Max_Num_Photos=('Number_of_photos','max'))
               .reindex(df['g'].cat.categories.unique())
              .rename_axis('Timeframe')
              .reset_index()
              .assign(Loc=lambda x: x.Max_Year.str[1],
                      Max_Year=lambda x: x.Max_Year.str[0] ))

df = max_photos(df, 1998, 4)
print (df)
   Timeframe  Max_Year  Max_Num_Photos    Loc
0  1998-2001    1998.0            40.0   loc8
1  2002-2005    2004.0            33.0  loc14
2  2006-2009    2006.0            24.0  loc16
3  2010-2013       NaN             NaN    NaN
4  2014-2017    2015.0            17.0  loc17

推荐阅读