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 相关文章推荐
利用打码兔和超人打码自封装的打码类分享
Mar 16 Python
python进程类subprocess的一些操作方法例子
Nov 22 Python
利用python生成一个导出数据库的bat脚本文件的方法
Dec 30 Python
Python3利用SMTP协议发送E-mail电子邮件的方法
Sep 30 Python
TensorFlow高效读取数据的方法示例
Feb 06 Python
Python中asyncio模块的深入讲解
Jun 10 Python
用python求一个数组的和与平均值的实现方法
Jun 29 Python
python新式类和经典类的区别实例分析
Mar 23 Python
Python 实现打印单词的菱形字符图案
Apr 12 Python
解决redis与Python交互取出来的是bytes类型的问题
Jul 16 Python
Python 使用双重循环打印图形菱形操作
Aug 09 Python
Python爬虫之App爬虫视频下载的实现
Dec 08 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中heredoc的使用方法
2013/06/17 PHP
如何解决CI框架的Disallowed Key Characters错误提示
2013/07/05 PHP
Zend Framework教程之Zend_Controller_Plugin插件用法详解
2016/03/07 PHP
PHP页面跳转实现延时跳转的方法
2016/12/10 PHP
PHP反射机制原理与用法详解
2017/02/15 PHP
php使用fputcsv实现大数据的导出操作详解
2020/02/27 PHP
Jquery.addClass始终无效原因分析
2013/09/08 Javascript
判断JS对象是否拥有某种属性的两种方式
2013/12/02 Javascript
js控制输入框获得和失去焦点时状态显示的方法
2015/01/30 Javascript
Javascript writable特性介绍
2015/02/27 Javascript
JS实现仿Windows经典风格的选项卡Tab切换代码
2015/10/20 Javascript
基于Javascript实现倒计时功能
2016/02/22 Javascript
javascript加减乘除的简单实例
2016/07/12 Javascript
javascript 小数乘法结果错误的处理方法
2016/07/28 Javascript
JS限制条件补全问题实例分析
2016/12/16 Javascript
vue-resource 拦截器使用详解
2017/02/21 Javascript
JS调用安卓手机摄像头扫描二维码
2018/10/16 Javascript
Vue.js递归组件实现组织架构树和选人功能
2019/07/04 Javascript
layui数据表格 table.render 报错的解决方法
2019/09/29 Javascript
python实现问号表达式(?)的方法
2013/11/27 Python
简单的通用表达式求10乘阶示例
2014/03/03 Python
跟老齐学Python之有容乃大的list(3)
2014/09/15 Python
python散点图实例之随机漫步
2018/08/27 Python
python 实现图片旋转 上下左右 180度旋转的示例
2019/01/24 Python
详解Python对JSON中的特殊类型进行Encoder
2019/07/15 Python
Python通过递归获取目录下指定文件代码实例
2019/11/07 Python
Python连接字符串过程详解
2020/01/06 Python
浅谈python输出列表元素的所有排列形式
2020/02/26 Python
Python3中的tuple函数知识点讲解
2021/01/03 Python
美国学校用品、教室和教学商店:Discount School Supply
2018/04/04 全球购物
车间组长岗位职责
2013/12/20 职场文书
股权转让协议书
2014/04/12 职场文书
暑期辅导班宣传单
2015/07/14 职场文书
酒店厨房管理制度
2015/08/06 职场文书
2016年“11.11”光棍节活动总结
2016/04/05 职场文书
postman中form-data、x-www-form-urlencoded、raw、binary的区别介绍
2022/01/18 HTML / CSS