继续前面的练习,之前的文章参考:
- pandas实例-了解你的数据-Chipotle
- pandas实例-筛选与排序-Chipotle
- pandas实例-数据可视化-Chipotle
- pandas实例-了解你的数据-Occupation
- pandas实例-筛选与过滤-Euro 12
- pandas实例-筛选与过滤-Fictional Army
- pandas实例-聚合-Alcohol Consumption
这个Occupation数据集,我们之前用过,可以在回顾一下
先看看原始数据:
注意两个点:
- 分隔符
- 有没有列名
- 其他的未知情况
df = pd.read_csv(data_path , sep='|' , header=None , names=['user_id' , 'age' , 'gender' , 'occupation' , 'zip_code'])
1. 每种职业的平均年龄
df.groupby('occupation')['age'].mean().sort_values(ascending=False)
注意:
- 聚合函数
groupby
的使用 - 求指定字段的平均值
2. 求每种职业的男女比例,并且降序排列
这个题目有点儿复杂了,反正和写SQL一样,
我们得知道:
- 每种职业的总人数
df_occupation = df.groupby('occupation')['user_id'].count()
- 每种职业的男、女人数分别是多少
df_occupation_gender = df.groupby(['occupation' , 'gender'])['user_id'].count()
然后,就是除法了,可以直接除
df_occupation_gender/df_occupation
或者使用函数来除
df_rs = df_occupation_gender.divide(df_occupation)
把百分比再格式化一下
df_rs.apply(lambda x: '{:.2%}'.format( x ) )
这种方法,是不是有点儿麻烦,我是觉得步骤有点儿多,应该可以优化
原作者从另一个角度来实现的,学习下思路
作者没有直接根据gender来计算男女人数,而是写了个函数
def parse_gender(gender):
if gender == 'M':
return 1
else:
return 0
df['gender_male'] = df['gender'].apply(parse_gender)
df['gender_female'] = 1-df['gender'].apply(parse_gender)
这样,根据gender_male
和gender_female
直接sum就可以了
df_rs[['gender_male', 'gender_female'] ].sum()
然后再去除就可以了
df_rs[['gender_male', 'gender_female'] ].sum().div(df_rs['user_id'].count() , axis='index')
记录一个问题,刚刚想实现以下,如何把index转成列,就是下图:
这个df_rs
,是一个series,我想把这个gender转成column,类似SQL中的行转列操作,就顺便学习了一下
df_rs = df_rs.reset_index()
df_rs.pivot(index='occupation' , columns='gender' , values='user_id')
pandas还是很强大呀,这个pivot函数也得好好学习下
3. 对于每一种职业,求它们的最小年龄和最大年龄
df.groupby('occupation')['age'].agg(['min','max'])
4. 基于上一题,加上男女性别维度
也就是看每种职业的男女不同的年龄区间
df.groupby(['occupation' , 'gender'])['age'].agg(['mean' , 'min' , 'max'])
5. 同第2题
本来第2题是只要看男性占比,我就顺便看了男女,没想到第5题就是每种职业的男女占比
这里是另一种方法,思路一样,实现不同
df_gender = df.groupby(['occupation' , 'gender']).agg({'gender':'count'})
df_ocp = df.groupby(['occupation']).agg({'gender':'count'})
df_gender.div(df_ocp , level='occupation')