python pandas库——pivot使用心得

来源:互联网 发布:磁卡充值系统java 编辑:程序博客网 时间:2024/06/07 15:06

最近在做基于python的数据分析工作,引用第三方数据分析库——pandas(version 0.16)。
在做数据统计二维表转换的时候走了不少弯路,发现pivot()这个方法可以解决很多问题,让我少走一些弯路,节省了大量的代码。于是我这里对于pandas下dataframe的pivot()方法进行学习总结和应用,以便回顾和巩固知识。


以统计学生成绩信息为例。
在做学生成绩信息统计的时候,我们从学生各科考试成绩文件(.csv或.xls等)中把数据抽取上来。样本模拟数据(data_df)如下。

In [13]: print data_df  userNum  score subjectCode subjectName userName0   001     90        01         语文       张三1   002     96        01         语文       李四2   003     93        01         语文       王五3   001     87        02         数学       张三4   002     82        02         数学       李四5   003     80        02         数学       王五

要把上面二维表转换为每个人各科的成绩信息。就像咱们中学时期的成绩单一样。类似于

学籍号  姓名  班级  语文成绩  语文排名  数学成绩  数学排名                        ...

的一张二维表。

我之前的传统统计方式,给data_df根据学籍号进行groupby,再循环遍历该分组得到每个人的各科成绩信息,再统计到一张新表中,然后循环append每一张新表,可生成以上的样表。如果我们需要统计全年级的学生呢?可能一个年级有500个学生,那就是循环500次。此时我们需要统计一个市区内多校联考的学生呢?岂不是要循环成百上千次?实际情况,这样的做法使得我们的脚本跑的非常的慢。

直到我在pandas的官方api上查到pivot()的这个方法。
pandas给pivot的官方解释

大概的意思就是根据列对数据表进行重塑。这样理解实在晦涩难懂。我不喜欢长篇大论,更喜欢暴力一点的,use it and 直观感受它(这样做当然不可取,最好还是对它的方法理解透彻一些,以便了解他更多的适用场景)。

从官方api可以知道他有三个参数,第一个index是重塑的新表的索引名称是什么,第二个columns是重塑的新表的列名称是什么,一般来说就是被统计列的分组,第三个values就是生成新列的值应该是多少,如果没有,则会对data_df剩下未统计的列进行重新排列放到columns的上层。

直接上代码

In [20]: pivot_df = data_df.pivot(index='userNum', columns='subjectCode', values='score')

我们给能标识每个学生的学籍号userNum作为索引,因为我们是要统计每个学生,所以每个学生的信息作为一行。要生成语文成绩,数学成绩等,那么可以用标识学科的subjectCode作为每一列,最后,值,当然就是score给每个科目赋成绩值了!

以下是生成的结果

In [21]: print pivot_dfsubjectCode  01  02userNum001          90  87002          96  82003          93  80

这就生成了我们大致想要的样子了,之后可以再给pivot_df的列名进行调整,还有其整体样式的调整。

# 这只是其中一个方式,如有更好的方式,不吝赐教~# 列名称置空pivot_df.columns.name = None# 遍历每个学科对新表列名进行修改data_df_G = data_df.groupby(["subjectCode"], as_index=False)temp_count = 1for index, subject_df in data_df_G:    # 把成绩排名添加到各科成绩之后    pivot_df.insert(temp_count, "rank_" + str(index), pivot_df[index].rank(ascending=False, method='min'))    # 重命名各科成绩    pivot_df.rename(columns={index: ("score_" + str(index))}, inplace=True)    temp_count += 2# 把userNum添加的列中pivot_df['userNum'] = pivot_df.index# 索引名称置空pivot_df.index.name = Nonetemp_df = data_df.loc[:, ["userNum", "userName"]]temp_df.drop_duplicates(inplace=True)# 剩余列拼接pivot_df = temp_df.merge(pivot_df, on="userNum", how="left")

最后生成的样式,大致能满足我们需要的东西了

In [30]: print(pivot_df)  userNum userName  score_01  rank_01  score_02  rank_020   001       张三      90        3        87        11   002       李四      96        1        82        22   003       王五      93        2        80        3

文中若有表述不当或实现不妥的地方,欢迎指正!

原创粉丝点击