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 相关文章推荐
用C++封装MySQL的API的教程
May 06 Python
matplotlib绘图实例演示标记路径
Jan 23 Python
django中send_mail功能实现详解
Feb 06 Python
Python结合ImageMagick实现多张图片合并为一个pdf文件的方法
Apr 24 Python
Pandas读取MySQL数据到DataFrame的方法
Jul 25 Python
对python读取zip压缩文件里面的csv数据实例详解
Feb 08 Python
Python3并发写文件与Python对比
Nov 20 Python
Numpy之将矩阵拉成向量的实例
Nov 30 Python
Django接收照片储存文件的实例代码
Mar 07 Python
Django 5种类型Session使用方法解析
Apr 29 Python
Python pip install之SSL异常处理操作
Sep 03 Python
python实现excel公式格式化的示例代码
Dec 23 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
怎么样可以把 phpinfo()屏蔽掉?
2006/11/24 PHP
PHPMailer 中文使用说明小结
2010/01/22 PHP
PHP 开发环境配置(Zend Server安装)
2010/04/28 PHP
解析php入库和出库
2013/06/25 PHP
PHP获取客户端真实IP地址的5种情况分析和实现代码
2014/07/08 PHP
一个php生成16位随机数的代码(两种方法)
2014/09/16 PHP
php计算整个目录大小的方法
2015/06/19 PHP
PHP 实现手机端APP支付宝支付功能
2018/06/07 PHP
Laravel框架运行出错提示RuntimeException No application encryption key has been specified.解决方法
2019/04/02 PHP
javascript 遍历验证所有文本框的值
2009/08/27 Javascript
JS 动态获取节点代码innerHTML分析 [IE,FF]
2009/11/30 Javascript
Jsonp 跨域的原理以及Jquery的解决方案
2011/06/27 Javascript
JavaScript italics方法入门实例(把字符串显示为斜体)
2014/10/17 Javascript
js实现禁止中文输入的方法
2015/01/14 Javascript
所见即所得的富文本编辑器bootstrap-wysiwyg使用方法详解
2016/05/27 Javascript
JS只能输入正整数的简单实例
2016/10/07 Javascript
Bootstrap中定制LESS-颜色及导航条(推荐)
2016/11/21 Javascript
获取jqGrid中选择的行的数据
2016/11/30 Javascript
javascript prototype原型详解(比较基础)
2016/12/26 Javascript
JavaScript 数据类型详解
2017/03/13 Javascript
AngularJS实现动态添加Option的方法
2017/05/17 Javascript
提升页面加载速度的插件InstantClick
2017/09/12 Javascript
ES6 javascript中class静态方法、属性与实例属性用法示例
2017/10/30 Javascript
Vue 通过自定义指令回顾v-内置指令(小结)
2018/09/03 Javascript
详解async/await 异步应用的常用场景
2019/05/13 Javascript
[02:55]2018DOTA2国际邀请赛勇士令状不朽珍藏Ⅲ饰品一览
2018/08/01 DOTA
Python存取XML的常见方法实例分析
2017/03/21 Python
python 网络编程详解及简单实例
2017/04/25 Python
python通过实例讲解反射机制
2019/10/17 Python
python标准库sys和OS的函数使用方法与实例详解
2020/02/12 Python
Python单例模式的四种创建方式实例解析
2020/03/04 Python
奥巴马演讲稿
2014/01/08 职场文书
大学新生欢迎词
2014/01/10 职场文书
有限责任公司股东合作协议书
2014/12/02 职场文书
离职告别感言
2015/08/04 职场文书
启动Tomcat时出现大量乱码的解决方法
2021/06/21 Java/Android