2017-04-07 74 views
3

我想计算一组使用熊猫的人的周转率。该组的规模可能会发生变化,但我想知道每年离开的人数百分比。熊猫:如何计算周转率?

用一个例子更好地解释。这里是我的样本数据:

teachers year 
0  John 2007 
1  Paul 2007 
2  Mary 2007 

3  John 2008 
4  Paul 2008 
5  Abel 2008 
6  Watt 2008 

7  John 2009 
8  Mary 2009 

我想在此数据集到达:

year turnover 
2008 .33333 
2009 .75 

在第一年,玛丽离开了,在第二年的保罗,亚伯和瓦离开。它会有一些偏见:如果这个组织缩小了,那么流失率会更大。

+0

如果玛丽2010年离开,但卡尔加入同一年,换手率是0.0还是0.5? – pshep123

+0

@ pshep123:它始终基于过去一年中停留在当年的人数。所以约翰会在2009年停留,而换手率是0.5。他可能是一个愤怒的老板,因为它是从一开始就存活下来的人:-) – neves

+0

2008年不是它应该是.333吗? 2007年有3人,剩下2人。 – jdehesa

回答

3

该计划

  • 我要设定'year''teachers'指数,所以我assign一个虚拟变量提前。
  • 我想要有'year'作为我的索引,所以我unstack'teachers'放在列中。我使用fill_value=0选项填写教师不在某一年的零年。
  • 使用diff并检查是否等于-1标识周转事件。 sum(1)总结所有周转事件。
  • d1.sum(1).shift()统计上一年度的所有教师。
  • 分得到营业额。

d1 = pd.Series(1, [df.year, df.teachers]).unstack(fill_value=0) 
d1.diff().eq(-1).sum(1).div(d1.sum(1).shift(), 0).dropna() 

year 
2008 0.333333 
2009 0.750000 
dtype: float64 

正如评论所指出的@jrjc,我的第一行是一个crosstab。考虑到这一点,我们可以减少代码:

d1 = pd.crosstab(df.year, df.teachers) 
d1.diff().eq(-1).sum(1).div(d1.sum(1).shift(), 0).dropna() 

一个使用pipe

pd.crosstab(df.year, df.teachers).pipe(
    lambda c: c.diff().eq(-1).sum(1).div(c.sum(1).shift(),0).dropna() 
) 
+0

你的'd1'只是一个交叉表:'d1 = pd.crosstab(df.year,df.teachers)'。下一行虽然不错! – jrjc

+0

@jrjc当然,你是对的......奇怪的是,在某些场景下,我的方式更快。然而,速度并不是我的焦点,“crosstab”更加优雅。 – piRSquared

1

这里有一个可能性:

from io import StringIO 

import numpy as np 
import pandas as pd 

data = pd.read_table(StringIO(
""" teachers year 
0  John 2007 
1  Paul 2007 
2  Mary 2007 
3  John 2008 
4  Paul 2008 
5  Abel 2008 
6  Watt 2008 
7  John 2009 
8  Mary 2009""" 
), delim_whitespace=True, index_col=0) 

data['presence'] = 1 
teacher_presence = data.groupby(['teachers', 'year']).count().unstack(1).fillna(0) 
teacher_presence.columns = teacher_presence.columns.droplevel(0) 

teacher_remain = teacher_presence.iloc[:, 1:] * teacher_presence.iloc[:, :-1].values 
turnover = 1 - teacher_remain.sum()/teacher_presence.iloc[:, :-1].sum().values 
turnover.name = 'turnover' 

print(turnover) 

结果:

year 
2008 0.333333 
2009 0.750000 
Name: turnover, dtype: float64 
0

您也可以分组后教师转换成set,再行执行这组操作。

In [72]: t = df.groupby('year')['teachers'].apply(lambda x: set(x.values.tolist())) 

In [73]: t 
Out[73]: 
year 
2007   {John, Paul, Mary} 
2008 {John, Abel, Paul, Watt} 
2009    {John, Mary} 
Name: teachers, dtype: object 

In [76]: t.combine(t.shift(), lambda a, b: len(b-a)/len(b) if isinstance(b, set) else np.nan).dropna() 
Out[76]: 
year 
2008 0.333333 
2009  0.75 
Name: teachers, dtype: object