8. 用时间戳和另一列分组

  1. # 读取employee数据集,用HIRE_DATE列创造一个DatetimeIndex
  2. In[131]: employee = pd.read_csv('data/employee.csv',
  3. parse_dates=['JOB_DATE', 'HIRE_DATE'],
  4. index_col='HIRE_DATE')
  5. employee.head()
  6. Out[131]:

8. 用时间戳和另一列分组 - 图1

  1. # 对性别做分组,查看二者的工资
  2. In[132]: employee.groupby('GENDER')['BASE_SALARY'].mean().round(-2)
  3. Out[132]: GENDER
  4. Female 52200.0
  5. Male 57400.0
  6. Name: BASE_SALARY, dtype: float64
  1. # 根据聘用日期,每10年分一组,查看工资情况
  2. In[133]: employee.resample('10AS')['BASE_SALARY'].mean().round(-2)
  3. Out[133]: HIRE_DATE
  4. 1958-01-01 81200.0
  5. 1968-01-01 106500.0
  6. 1978-01-01 69600.0
  7. 1988-01-01 62300.0
  8. 1998-01-01 58200.0
  9. 2008-01-01 47200.0
  10. Freq: 10AS-JAN, Name: BASE_SALARY, dtype: float64
  1. # 如果要按性别和五年分组,可以在groupby后面调用resample
  2. In[134]: sal_avg = employee.groupby('GENDER').resample('10AS')['BASE_SALARY'].mean().round(-2)
  3. sal_avg
  4. Out[134]: GENDER HIRE_DATE
  5. Female 1975-01-01 51600.0
  6. 1985-01-01 57600.0
  7. 1995-01-01 55500.0
  8. 2005-01-01 51700.0
  9. 2015-01-01 38600.0
  10. Male 1958-01-01 81200.0
  11. 1968-01-01 106500.0
  12. 1978-01-01 72300.0
  13. 1988-01-01 64600.0
  14. 1998-01-01 59700.0
  15. 2008-01-01 47200.0
  16. Name: BASE_SALARY, dtype: float64
  1. # 对性别unstack
  2. In[135]: sal_avg.unstack('GENDER')
  3. Out[135]:

8. 用时间戳和另一列分组 - 图2

  1. # 上面数据的问题,是分组不恰当造成的。
  2. # 第一名男性受聘于1958年
  3. In[136]: employee[employee['GENDER'] == 'Male'].index.min()
  4. Out[136]: Timestamp('1958-12-29 00:00:00')
  5. # 第一名女性受聘于1975年
  6. In[137]: employee[employee['GENDER'] == 'Female'].index.min()
  7. Out[137]: Timestamp('1975-06-09 00:00:00')
  1. # 为了解决前面的分组问题,必须将日期和性别同时分组
  2. In[138]: sal_avg2 = employee.groupby(['GENDER', pd.Grouper(freq='10AS')])['BASE_SALARY'].mean().round(-2)
  3. sal_avg2
  4. Out[138]: GENDER HIRE_DATE
  5. Female 1968-01-01 NaN
  6. 1978-01-01 57100.0
  7. 1988-01-01 57100.0
  8. 1998-01-01 54700.0
  9. 2008-01-01 47300.0
  10. Male 1958-01-01 81200.0
  11. 1968-01-01 106500.0
  12. 1978-01-01 72300.0
  13. 1988-01-01 64600.0
  14. 1998-01-01 59700.0
  15. 2008-01-01 47200.0
  16. Name: BASE_SALARY, dtype: float64
  1. # 再对性别做unstack
  2. In[139]: sal_final = sal_avg2.unstack('GENDER')
  3. sal_final
  4. Out[139]:

8. 用时间戳和另一列分组 - 图3

原理

  1. # groupby返回对象包含resample方法,但相反却不成立
  2. In[140]: 'resample' in dir(employee.groupby('GENDER'))
  3. Out[140]: True
  4. In[141]: 'groupby' in dir(employee.resample('10AS'))
  5. Out[141]: False

更多

  1. # 通过加9,手工创造时间区间
  2. In[142]: years = sal_final.index.year
  3. years_right = years + 9
  4. sal_final.index = years.astype(str) + '-' + years_right.astype(str)
  5. sal_final
  6. Out[142]:

8. 用时间戳和另一列分组 - 图4

  1. # 也可以使用cut函数创造基于每名员工受聘年份的等宽间隔
  2. In[143]: cuts = pd.cut(employee.index.year, bins=5, precision=0)
  3. cuts.categories.values
  4. Out[143]: array([Interval(1958.0, 1970.0, closed='right'),
  5. Interval(1970.0, 1981.0, closed='right'),
  6. Interval(1981.0, 1993.0, closed='right'),
  7. Interval(1993.0, 2004.0, closed='right'),
  8. Interval(2004.0, 2016.0, closed='right')], dtype=object)
  9. In[144]: employee.groupby([cuts, 'GENDER'])['BASE_SALARY'].mean().unstack('GENDER').round(-2)
  10. Out[144]:

8. 用时间戳和另一列分组 - 图5