按子人口百分比进行多级分组
Multi-level groupby sub-population percentages
让我们考虑以下数据框:
df = {'Location': ['A','A','B','B','C','C','A','C','A'],
'Gender'['M','M','F','M','M','F','M','M','M'],
'Edu'['N','N','Y','Y','Y','N','Y','Y','Y'],
'Access1': [1,0,1,0,1,0,1,1,1], 'Access2': [1,1,1,0,0,1,0,0,1] }
df = pd.DataFrame(data=d, dtype=np.int8)
数据框的输出:
Access1 Access2 Edu Gender Location
0 1 1 N M A
1 0 1 N M A
2 1 1 Y F B
3 0 0 Y M B
4 1 0 Y M C
5 0 1 N F C
6 1 0 Y M A
7 1 0 Y M C
8 1 1 Y M A
然后我使用groupby来分析df中的频率
D0=df.groupby(['Location','Gender','Edu']).sum()
((D0/ D0.groupby(level = [0]).transform(sum))*100).round(3).astype(str) + '%'
输出:
Access1 Access2
Location Gender Edu
A M N 33.333% 66.667%
Y 66.667% 33.333%
B F Y 100.0% 100.0%
M Y 0.0% 0.0%
C F N 0.0% 100.0%
M Y 100.0% 0.0%
从这个输出中,我推断出位置 A 中 33.3% 的未受过教育的人可以访问服务 1 (=Access1) 是考虑到位置 A 中有 3 个人可以访问服务 1 的结果,其中 1 位未受过教育的人可以访问它 (=1/3)。
但是,希望获得不同的输出。我想将位置 A 的总共 4 名男性视为我的 100%。这群人中有 50% 没有受过教育。在这 50% 的未受过教育的男性中,有 25% 的人可以使用服务 1。因此,我希望在 table 中看到的百分比是 25%(A 区未受过教育的男性访问服务 1 的总数)。 groupby 是到达那里的正确方法吗?在考虑从每个位置的参考总人口中分解时,衡量服务 1 访问百分比的最佳方法是什么?
我认为需要将 D0
除以 a
系列映射的第一级 MultiIndex:
D0=df.groupby(['Location','Gender','Edu']).sum()
a = df['Location'].value_counts()
#alternative
#a = df.groupby(['Location']).size()
print (a)
A 4
C 3
B 2
Name: Location, dtype: int64
df1 = D0.div(D0.index.get_level_values(0).map(a.get), axis=0)
print (df1)
Access1 Access2
Location Gender Edu
A M N 0.250000 0.500000
Y 0.500000 0.250000
B F Y 0.500000 0.500000
M Y 0.000000 0.000000
C F N 0.000000 0.333333
M Y 0.666667 0.000000
详情:
print (D0.index.get_level_values(0).map(a.get))
Int64Index([4, 4, 2, 2, 3, 3], dtype='int64', name='Location')
让我们考虑以下数据框:
df = {'Location': ['A','A','B','B','C','C','A','C','A'],
'Gender'['M','M','F','M','M','F','M','M','M'],
'Edu'['N','N','Y','Y','Y','N','Y','Y','Y'],
'Access1': [1,0,1,0,1,0,1,1,1], 'Access2': [1,1,1,0,0,1,0,0,1] }
df = pd.DataFrame(data=d, dtype=np.int8)
数据框的输出:
Access1 Access2 Edu Gender Location
0 1 1 N M A
1 0 1 N M A
2 1 1 Y F B
3 0 0 Y M B
4 1 0 Y M C
5 0 1 N F C
6 1 0 Y M A
7 1 0 Y M C
8 1 1 Y M A
然后我使用groupby来分析df中的频率
D0=df.groupby(['Location','Gender','Edu']).sum()
((D0/ D0.groupby(level = [0]).transform(sum))*100).round(3).astype(str) + '%'
输出:
Access1 Access2
Location Gender Edu
A M N 33.333% 66.667%
Y 66.667% 33.333%
B F Y 100.0% 100.0%
M Y 0.0% 0.0%
C F N 0.0% 100.0%
M Y 100.0% 0.0%
从这个输出中,我推断出位置 A 中 33.3% 的未受过教育的人可以访问服务 1 (=Access1) 是考虑到位置 A 中有 3 个人可以访问服务 1 的结果,其中 1 位未受过教育的人可以访问它 (=1/3)。
但是,希望获得不同的输出。我想将位置 A 的总共 4 名男性视为我的 100%。这群人中有 50% 没有受过教育。在这 50% 的未受过教育的男性中,有 25% 的人可以使用服务 1。因此,我希望在 table 中看到的百分比是 25%(A 区未受过教育的男性访问服务 1 的总数)。 groupby 是到达那里的正确方法吗?在考虑从每个位置的参考总人口中分解时,衡量服务 1 访问百分比的最佳方法是什么?
我认为需要将 D0
除以 a
系列映射的第一级 MultiIndex:
D0=df.groupby(['Location','Gender','Edu']).sum()
a = df['Location'].value_counts()
#alternative
#a = df.groupby(['Location']).size()
print (a)
A 4
C 3
B 2
Name: Location, dtype: int64
df1 = D0.div(D0.index.get_level_values(0).map(a.get), axis=0)
print (df1)
Access1 Access2
Location Gender Edu
A M N 0.250000 0.500000
Y 0.500000 0.250000
B F Y 0.500000 0.500000
M Y 0.000000 0.000000
C F N 0.000000 0.333333
M Y 0.666667 0.000000
详情:
print (D0.index.get_level_values(0).map(a.get))
Int64Index([4, 4, 2, 2, 3, 3], dtype='int64', name='Location')