pandas.DataFrame的pivot()和unstack()实现行转列


Posted in Python onJuly 06, 2019

示例:有如下表需要进行行转列:

pandas.DataFrame的pivot()和unstack()实现行转列

代码如下:

# -*- coding:utf-8 -*-

import pandas as pd

import MySQLdb

from warnings import filterwarnings

# 由于create table if not exists总会抛出warning,因此使用filterwarnings消除

filterwarnings('ignore', category = MySQLdb.Warning)

from sqlalchemy import create_engine

import sys

if sys.version_info.major<3:

 reload(sys)

 sys.setdefaultencoding("utf-8")

 # 此脚本适用于python2和python3

host,port,user,passwd,db,charset="192.168.1.193",3306,"leo","mysql","test","utf8"

 

def get_df():

 global host,port,user,passwd,db,charset

 conn_config={"host":host, "port":port, "user":user, "passwd":passwd, "db":db,"charset":charset}

 conn = MySQLdb.connect(**conn_config)

 result_df=pd.read_sql('select UserName,Subject,Score from TEST',conn)

 return result_df

 

def pivot(result_df):

 df_pivoted_init=result_df.pivot('UserName','Subject','Score')

 df_pivoted = df_pivoted_init.reset_index() # 将行索引也作为DataFrame值的一部分,以方便存储数据库

 return df_pivoted_init,df_pivoted

 # 返回的两个DataFrame,一个是以姓名作index的,一个是以数字序列作index,前者用于unpivot,后者用于save_to_mysql

 

def unpivot(df_pivoted_init):

 # unpivot需要进行df_pivoted_init二维表格的行、列索引遍历,需要拼SQL因此不能使用save_to_mysql存数据,这里使用SQL和MySQLdb接口存

 insert_sql="insert into test_unpivot(UserName,Subject,Score) values "

 # 处理值为NaN的情况

 df_pivoted_init=df_pivoted_init.fillna(0)

 for col in df_pivoted_init.columns:

  for index in df_pivoted_init.index:

   value=df_pivoted_init.at[index,col]

   if value!=0:

    insert_sql=insert_sql+"('%s','%s',%s)" %(index,col,value)+','

 insert_sql = insert_sql.strip(',')

 global host, port, user, passwd, db, charset

 conn_config = {"host": host, "port": port, "user": user, "passwd": passwd, "db": db, "charset": charset}

 conn = MySQLdb.connect(**conn_config)

 cur=conn.cursor()

 cur.execute("create table if not exists test_unpivot like TEST")

 cur.execute(insert_sql)

 conn.commit()

 conn.close()

 

def save_to_mysql(df_pivoted,tablename):

 global host, port, user, passwd, db, charset

 """

 只有使用sqllite时才能指定con=connection实例,其他数据库需要使用sqlalchemy生成engine,engine的定义可以添加?来设置字符集和其他属性

 """

 conn="mysql://%s:%s@%s:%d/%s?charset=%s" %(user,passwd,host,port,db,charset)

 mysql_engine = create_engine(conn)

 df_pivoted.to_sql(name=tablename, con=mysql_engine, if_exists='replace', index=False)

 

# 从TEST表读取源数据至DataFrame结构

result_df=get_df()

# 将源数据行转列为二维表格形式

df_pivoted_init,df_pivoted=pivot(result_df)

# 将二维表格形式的数据存到新表test中

save_to_mysql(df_pivoted,'test')

# 将被行转列的数据unpivot,存入test_unpivot表中

unpivot(df_pivoted_init)

结果如下:

pandas.DataFrame的pivot()和unstack()实现行转列

关于Pandas DataFrame类自带的pivot方法:

DataFrame.pivot(index=None, columns=None, values=None):

Return reshaped DataFrame organized by given index / column values.

这里只有3个参数,是因为pivot之后的结果一定是二维表格,只需要行列及其对应的值,而且也因为是二维表格,unpivot之后is_pass列是肯定会丢失的,因此一开始我就没查这个列。

补充说明:

在学习到Pandas的层次化索引部分时发现了2个很有意思的函数,也可以进行行列互转,其用法如下:(很久之后我才意识到,pivot只是封装了unstack的一个快捷方式而已,其本质上还是先用set_index建立层次化索引,然后用unstack进行重塑,就像我在下面示例做的操作)

# -*- coding:utf-8 -*-

import pandas as pd

import MySQLdb

from warnings import filterwarnings

# 由于create table if not exists总会抛出warning,因此使用filterwarnings消除

filterwarnings('ignore', category = MySQLdb.Warning)

from sqlalchemy import create_engine

import sys

if sys.version_info.major<3:

 reload(sys)

 sys.setdefaultencoding("utf-8")

 # 此脚本适用于python2和python3

host,port,user,passwd,db,charset="192.168.1.193",3306,"leo","mysql","test","utf8"

 

def get_df():

 global host,port,user,passwd,db,charset

 conn_config={"host":host, "port":port, "user":user, "passwd":passwd, "db":db,"charset":charset}

 conn = MySQLdb.connect(**conn_config)

 result_df=pd.read_sql('select UserName,Subject,Score from TEST',conn)

 return result_df

 

def pivot(result_df):

 df_pivoted_init=result_df.pivot('UserName','Subject','Score')

 df_pivoted = df_pivoted_init.reset_index() # 将行索引也作为DataFrame值的一部分,以方便存储数据库

 return df_pivoted_init,df_pivoted

 # 返回的两个DataFrame,一个是以姓名作index的,一个是以数字序列作index,前者用于unpivot,后者用于save_to_mysql

 

def unpivot(df_pivoted_init):

 # unpivot需要进行df_pivoted_init二维表格的行、列索引遍历,需要拼SQL因此不能使用save_to_mysql存数据,这里使用SQL和MySQLdb接口存

 insert_sql="insert into test_unpivot(UserName,Subject,Score) values "

 # 处理值为NaN的情况

 df_pivoted_init=df_pivoted_init.fillna(0)

 for col in df_pivoted_init.columns:

  for index in df_pivoted_init.index:

   value=df_pivoted_init.at[index,col]

   if value!=0:

    insert_sql=insert_sql+"('%s','%s',%s)" %(index,col,value)+','

 insert_sql = insert_sql.strip(',')

 global host, port, user, passwd, db, charset

 conn_config = {"host": host, "port": port, "user": user, "passwd": passwd, "db": db, "charset": charset}

 conn = MySQLdb.connect(**conn_config)

 cur=conn.cursor()

 cur.execute("create table if not exists test_unpivot like TEST")

 cur.execute(insert_sql)

 conn.commit()

 conn.close()

 

def save_to_mysql(df_pivoted,tablename):

 global host, port, user, passwd, db, charset

 """

 只有使用sqllite时才能指定con=connection实例,其他数据库需要使用sqlalchemy生成engine,engine的定义可以添加?来设置字符集和其他属性

 """

 conn="mysql://%s:%s@%s:%d/%s?charset=%s" %(user,passwd,host,port,db,charset)

 mysql_engine = create_engine(conn)

 df_pivoted.to_sql(name=tablename, con=mysql_engine, if_exists='replace', index=False)

 

# 从TEST表读取源数据至DataFrame结构

result_df=get_df()

# 将源数据行转列为二维表格形式

df_pivoted_init,df_pivoted=pivot(result_df)

# 将二维表格形式的数据存到新表test中

save_to_mysql(df_pivoted,'test')

# 将被行转列的数据unpivot,存入test_unpivot表中

unpivot(df_pivoted_init)

以上利用了Pandas的层次化索引,实际上这也是层次化索引一个主要的用途,结合本例我们可以把代码改成如下:

result_df=pd.read_sql('select UserName,Subject,Score from TEST',conn)

# 在从数据库中获取的数据格式是这样的:

    UserName Subject Score

0    张三   语文  80.0

1    张三   数学  90.0

2    张三   英语  70.0

3    张三   生物  85.0

4    李四   语文  80.0

5    李四   数学  92.0

6    李四   英语  76.0

7    王五   语文  60.0

8    王五   数学  82.0

9    王五   英语  96.0

10    王五   生物  78.0

# 如果要使用层次化索引,那么我们只需要把UserName和Subject列设置为层次化索引,Score为其对应的值即可,我们借用set_index()函数:

df=result_df.set_index(['UserName','Subject'])

In [112]: df.unstack()

Out[112]: 

     Score         

Subject   数学  生物  英语  语文

UserName            

张三    90.0 85.0 70.0 80.0

李四    92.0  NaN 76.0 80.0

王五    82.0 78.0 96.0 60.0

# 使用stack可以将unstack的结果转回来,这样就也在形式上实现了行列互转,之后的操作基本一致了。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python sort、sorted高级排序技巧
Nov 21 Python
python基于pyDes库实现des加密的方法
Apr 29 Python
Python 多线程Threading初学教程
Aug 22 Python
python实现快速排序的示例(二分法思想)
Mar 12 Python
Python爬取数据并写入MySQL数据库的实例
Jun 21 Python
Python 使用PIL中的resize进行缩放的实例讲解
Aug 03 Python
解决python3运行selenium下HTMLTestRunner报错的问题
Dec 27 Python
python matplotlib实现双Y轴的实例
Feb 12 Python
python异步存储数据详解
Mar 19 Python
Pandas之DataFrame对象的列和索引之间的转化
Jun 25 Python
jupyter lab文件导出/下载方式
Apr 22 Python
Python 制作查询商品历史价格的小工具
Oct 20 Python
从列表或字典创建Pandas的DataFrame对象的方法
Jul 06 #Python
pandas的qcut()方法详解
Jul 06 #Python
pandas 层次化索引的实现方法
Jul 06 #Python
pandas删除行删除列增加行增加列的实现
Jul 06 #Python
Python使用Pandas库实现MySQL数据库的读写
Jul 06 #Python
python 实现的发送邮件模板【普通邮件、带附件、带图片邮件】
Jul 06 #Python
Python 微信爬虫完整实例【单线程与多线程】
Jul 06 #Python
You might like
PHP_MySQL教程-第一天
2007/03/18 PHP
PHP SPL标准库中的常用函数介绍
2015/05/11 PHP
Zend Framework基本页面布局分析
2016/03/19 PHP
PHP 获取 ping 时间的实现方法
2017/09/29 PHP
用jscript实现新建和保存一个word文档
2007/06/15 Javascript
用js实现随机返回数组的一个元素
2007/08/13 Javascript
Jquery 基础学习笔记之文档处理
2009/05/29 Javascript
javascript 日期常用的方法
2009/11/11 Javascript
jquery实现微博文字输入框 输入时显示输入字数 效果实现
2013/07/12 Javascript
JavaScript实现自动变换表格边框颜色
2015/05/08 Javascript
JavaScript中rem布局在react中的应用
2015/12/09 Javascript
Javascript中引用类型传递的知识点小结
2017/03/06 Javascript
浅谈VUE单页应用首屏加载速度优化方案
2018/08/28 Javascript
vue引入静态js文件的方法
2020/06/20 Javascript
从零学Python之入门(四)运算
2014/05/27 Python
Python开发如何在ubuntu 15.10 上配置vim
2016/01/25 Python
TensorFlow入门使用 tf.train.Saver()保存模型
2018/04/24 Python
Scrapy框架使用的基本知识
2018/10/21 Python
python动态文本进度条的实例代码
2020/01/22 Python
基于Django signals 信号作用及用法详解
2020/03/28 Python
解决启动django,浏览器显示“服务器拒绝访问”的问题
2020/05/13 Python
keras读取训练好的模型参数并把参数赋值给其它模型详解
2020/06/15 Python
flask开启多线程的具体方法
2020/08/02 Python
如何通过python计算圆周率PI
2020/11/11 Python
CSS3教程(10):CSS3 HSL声明设置颜色
2009/04/02 HTML / CSS
英国网上花店:Bunches
2016/11/29 全球购物
美国在线打印网站:Overnight Prints
2018/10/11 全球购物
俄罗斯茶和咖啡网上商店:Tea.ru
2021/01/26 全球购物
师德师风个人反思
2014/04/28 职场文书
优秀护士先进事迹
2014/05/08 职场文书
陈安之励志演讲稿
2014/08/21 职场文书
档案工作汇报材料
2014/08/21 职场文书
销售员未完成销售业绩的检讨书
2014/10/12 职场文书
2014最新自愿离婚协议书范本
2014/11/19 职场文书
2014年妇联工作总结
2014/11/21 职场文书
琅琊山导游词
2015/02/05 职场文书