import numpy as npimport pandas as pd
下列数据描述的是每个机顶盒观看各个电视频道的时长,通过这组原始数据,查找出每个机顶盒偏好的频道并进行排序,原始数据如下:
data
目标数据如下:偏好频道1到偏好频道4的排序依据是观看时长降序排列,也就是当前机顶盒观看偏好频道1的时长最长,观看偏好频道4的时长最短,如何才能在原始数据的基础上得到下列数据呢?
思路:实际上,上述两个图表之间的关系可以看成每个机顶盒设备号是一组,然后组内按照时长进行降序排序,排序后,时长列舍弃不要,把频道名称列转换成行即可,按照这个思路,我们一步一步实现。
第一步:按照机顶盒设备号分组,组内按照时长降序排序,这两步可以用一行代码实现,具体如下:
data.groupby(["机顶盒设备号"]).apply(lambda x :x.sort_values("时长",ascending=False))
</style>
机顶盒设备号 |
频道名称 |
时长 |
||
机顶盒设备号 |
||||
10001 |
0 |
10001 |
东方卫视 |
1.764052 |
1 |
10001 |
翡翠台 |
0.400157 |
|
10002 |
3 |
10002 |
江苏卫视 |
2.240893 |
4 |
10002 |
珠江电影 |
1.867558 |
|
2 |
10002 |
浙江卫视 |
0.978738 |
|
5 |
10002 |
卡酷动画 |
0.977278 |
|
10003 |
6 |
10003 |
湖南卫视 |
0.950088 |
9 |
10003 |
广东卫视 |
0.410599 |
|
7 |
10003 |
中央5台 |
0.151357 |
|
8 |
10003 |
北京卫视 |
0.103219 |
|
10004 |
11 |
10004 |
江西卫视 |
1.454274 |
10 |
10004 |
福建卫视 |
0.144044 |
|
10005 |
12 |
10005 |
河北卫视 |
0.761038 |
14 |
10005 |
陕西卫视 |
0.443863 |
|
13 |
10005 |
河南卫视 |
0.121675 |
</div>
对上述代码进行简单解释,data.groupby(["机顶盒设备号"])表示对名字为data的数据集进行分组,分组的依据是"机顶盒设备号"这一列,默认把分组依据作为分组数据进行聚合后的行索引(可以通过as_index参数进行设置)。
接下来进行组内排序,对所有小组中的数据进行相同的操作可以通过apply方法实现,apply方法接收的参数是一个函数,目前的需求是组内排序,所以我们传入apply方法中的函数需要具有排序功能。
分组后的每一个小组都是一个小的dataframe,所以apply中接收的函数,得是能够为dataframe排序的函数才行。大家最先想到的可能就是dataframe支持的sort_values方法,但是需要注意的是sort_values是dataframe支持的方法,不是通用函数,不能直接作为参数传递给apply。
既然是对每个小的dataframe按照时长进行排序,我们可以借助匿名函数,匿名函数中的参数就是每个分组,即分组后的小dataframe,用这个小dataframe调用sort_values方法就可以了,注意填写上排序的依据–"时长",还有排序的方向ascending=False,降序排序。
以上,得到的结果好像没有什么问题,的确实现了组内排序,但是,有一个细节问题,就是索引,从下图可以看出,索引不是组内索引,我们还需要修改索引,即每一组的索引都是从0到n-1。如果不修改索引,每一组的索引都不一样的话,没有办法得到目标的结果(有兴趣的小伙伴可以不修改索引试验一下)。
其实修改组内索引这一步在刚才的代码里添加一个参数即可,在对dataframe进行排序的sort_values方法中,有一个参数ignore_index表示是否忽略原索引,忽略原索引即对组内索引进行重置,所以只需要添加这一个参数就可以了,具体代码及效果如下:
dff = data.groupby(["机顶盒设备号"]).apply(lambda x :x.sort_values("时长",ascending=False,ignore_index=True))
dff
第二步:到这一步,已经基本时实现了查找每个机顶盒的偏好频道,但是,这种形式看起来不太直观。
对于我们的目标来说,时长只在排序的时候有作用,所以,在这个表中,有用的只是索引列和频道名称,我们只需要把频道名称从列转换成行即可。这个转换用到的是unstack方法,即把列转换成行。
在转换的时候,不要整个数据集转换,有用的数据提取出来进行转换即可,有用的数据就是索引列和频道名称,提取出来的数据如下:
dff["频道名称"]
机顶盒设备号 10001 0 东方卫视 1 翡翠台10002 0 江苏卫视 1 珠江电影 2 浙江卫视 3 卡酷动画10003 0 湖南卫视 1 广东卫视 2 中央5台 3 北京卫视10004 0 江西卫视 1 福建卫视10005 0 河北卫视 1 陕西卫视 2 河南卫视Name: 频道名称, dtype: object
其中机顶盒设备号和rangeindex组成的多重索引,数据只有频道名称,运用unstack把频道名称转换成行数据,代码如下:
dff1 = dff["频道名称"].unstack()dff1
</style>
0 |
1 |
2 |
3 |
|
机顶盒设备号 |
||||
10001 |
东方卫视 |
翡翠台 |
NaN |
NaN |
10002 |
江苏卫视 |
珠江电影 |
浙江卫视 |
卡酷动画 |
10003 |
湖南卫视 |
广东卫视 |
中央5台 |
北京卫视 |
10004 |
江西卫视 |
福建卫视 |
NaN |
NaN |
10005 |
河北卫视 |
陕西卫视 |
河南卫视 |
NaN |
</div>
第三步:现在只需要按照要求修改列名即可,代码如下:
dff1.columns=["偏好频道1","偏好频道2","偏好频道3","偏好频道4"]dff1
</style>
偏好频道1 |
偏好频道2 |
偏好频道3 |
偏好频道4 |
|
机顶盒设备号 |
||||
10001 |
东方卫视 |
翡翠台 |
NaN |
NaN |
10002 |
江苏卫视 |
珠江电影 |
浙江卫视 |
卡酷动画 |
10003 |
湖南卫视 |
广东卫视 |
中央5台 |
北京卫视 |
10004 |
江西卫视 |
福建卫视 |
NaN |
NaN |
10005 |
河北卫视 |
陕西卫视 |
河南卫视 |
NaN |
</div>
这样就能直观的看出,每一个机顶盒的偏好频道了。
声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:dandanxi6@qq.com