iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > Python >pandas.DataFrame的piv
  • 533
分享到

pandas.DataFrame的piv

pandasDataFramepiv 2023-01-30 22:01:57 533人浏览 八月长安

Python 官方文档:入门教程 => 点击学习

摘要

示例: 有如下表需要进行行转列: 代码如下: # -*- coding:utf-8 -*- import pandas as pd import Mysqldb from warnings import filterwarnings

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

代码如下:

# -*- 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方法:
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进行重塑,就像我在下面示例做的操作)
df=pd.DataFrame(np.random.randn(20).reshape(4,5),index=[['a','a','b','b'],[1,2,3,4]],columns=[10,20,30,40,50])
In [96]: df
Out[96]: 
           10        20        30        40        50
a 1  0.945775  0.768337  0.851630 -1.050475 -1.102554
  2 -0.366129  0.353388 -0.722637 -0.056877  1.178270
b 3  0.885536  0.210911  2.067309  1.283721 -0.432906
  4  0.173504  1.263630  1.264698  0.913879  1.156815
In [98]: df.stack()
Out[98]: 
a  1  10    0.945775
      20    0.768337
      30    0.851630
      40   -1.050475
      50   -1.102554
   2  10   -0.366129
      20    0.353388
      30   -0.722637
      40   -0.056877
      50    1.178270
b  3  10    0.885536
      20    0.210911
      30    2.067309
      40    1.283721
      50   -0.432906
   4  10    0.173504
      20    1.263630
      30    1.264698
      40    0.913879
      50    1.156815
In [99]: df.stack().unstack()
Out[99]: 
           10        20        30        40        50
a 1  0.945775  0.768337  0.851630 -1.050475 -1.102554
  2 -0.366129  0.353388 -0.722637 -0.056877  1.178270
b 3  0.885536  0.210911  2.067309  1.283721 -0.432906
  4  0.173504  1.263630  1.264698  0.913879  1.156815

以上利用了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的结果转回来,这样就也在形式上实现了行列互转,之后的操作基本一致了。

--结束END--

本文标题: pandas.DataFrame的piv

本文链接: https://www.lsjlt.com/news/179972.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作