Python和MySQL对比(4):用Pandas 实现MySQL的行列转换语法效果

news2025/1/19 20:36:30

文章目录

  • 一、前言
  • 二、语法对比
    • 数据表
    • concat(多列合并为一列)
    • group_concat(多行合并为一行)
    • 一列拆分为多列
    • 一行拆分为多行
    • 多行转为多列
    • 多列转为多行
  • 三、小结

一、前言

环境:
windows11 64位
Python3.9
MySQL8
pandas1.4.2

本文主要介绍行列转换几个常见的行列转换问题在 Python 和 MySQL 的实现及语法对比,包含了:多列合并为一列、多行合并为一行、一列拆分为多列、一行拆分为多行、多行转多列、多列转多行。

注:Python是很灵活的语言,达成同一个目标或有多种途径,我提供的只是其中一种解决方法,大家有其他的方法也欢迎留言讨论。

二、语法对比

数据表

本次使用的数据如下。
使用 Python 构建该数据集的语法如下:

import pandas as pd
import numpy as np

df1 = pd.DataFrame({ 'col1' : list(range(1,7))
                    ,'col2' : ['AA','AA','AA','BB','BB','BB']#list('AABCA')
                    ,'col3' : ['X',np.nan,'Da','Xi','Xa','xa']
                    ,'col4' : [10,5,3,5,2,None]
                    ,'col5' : [90,60,60,80,50,50]
                    ,'col6' : ['Abc','Abc','bbb','Cac','Abc','bbb']
                   })
df2 = pd.DataFrame({'col2':['AA','BB','CC'],'col7':[1,2,3],'col4':[5,6,7]})
df3 = pd.DataFrame({'col2':['AA','DD','CC'],'col8':[5,7,9],'col9':['abc,bcd,fgh','rst,xyy,ijk','nml,opq,wer']})

注:直接将代码放 jupyter 的 cell 跑即可。后文都直接使用df1df2df3调用对应的数据。(注意,该数据集 df3 和上一节不同)

使用 MySQL 构建该数据集的语法如下:

with t1 as(
  select  1 as col1, 'AA' as col2, 'X' as col3, 10.0 as col4, 90 as col5, 'Abc' as col6 union all
  select  2 as col1, 'AA' as col2, null as col3, 5.0 as col4, 60 as col5, 'Abc' as col6 union all
  select  3 as col1, 'AA' as col2, 'Da' as col3, 3.0 as col4, 60 as col5, 'bbb' as col6 union all
  select  4 as col1, 'BB' as col2, 'Xi' as col3, 5.0 as col4, 80 as col5, 'Cac' as col6 union all
  select  5 as col1, 'BB' as col2, 'Xa' as col3, 2.0 as col4, 50 as col5, 'Abc' as col6 union all
  select  6 as col1, 'BB' as col2, 'xa' as col3, null as col4, 50 as col5, 'bbb' as col6 
)
,t2 as(
  select  'AA' as col2, 1 as col7, 5 as col4 union all
  select  'BB' as col2, 2 as col7, 6 as col4 union all
  select  'CC' as col2, 3 as col7, 7 as col4 
)
,t3 as(
  select  'AA' as col2, 5 as col8, 'abc,bcd,fgh' as col9 union all
  select  'DD' as col2, 7 as col8, 'rst,xyy,ijk' as col9 union all
  select  'CC' as col2, 9 as col8, 'nml,opq,wer' as col9 
)
select * from t1;

注:直接将代码放 MySQL 代码运行框跑即可。后文跑 SQL 代码时,默认带上数据集(代码的1~18行),仅展示查询语句,如第19行。(注意,该数据集 t3 和上一节不同,多了col9列)

对应关系如下:

Python 数据集MySQL 数据集
df1t1
df2t2
df3t3

concat(多列合并为一列)

MySQL 使用concat()可以将多列拼接为一列,除了该函数,还有concat_ws(),二者的用法和返回的结果有一些不同。concat()是将所有需要拼接的字段或字符用逗号隔开放到括号里,而concat_ws()需要指定分隔符,统一使用该分隔符对数据进行分割,具体看以下例子。

两个非空字段拼接-concat/concat_ws
当 MySQL 的字段都是非空时,concat()concat_ws()如果使用相同的分隔符,结果一致。
在 Python 中,可以使用+apply()+lambdastr.cat()等方法实现相同的结果。
需要注意的是,MySQL 会对数值字段col5进行隐式转换为字符串,然后进行拼接,而 Python 不能,需要手动进行转化,可以使用astype()map()等进行转化。

语言PythonMySQL
代码【Python1】
df1_1 = df1.copy()
df1_1[‘col5’] = df1_1.col5.astype(‘str’)
df1_1.col2+‘‘+df1_1.col5
【Python2】
df1_1 = df1.copy()
df1_1[‘col5’] = df1_1.col5.astype(‘str’)
df1_1.apply(lambda x:x.col2+’
’+x.col5,axis=1)
【Python3】
df1_1 = df1.copy()
df1_1[‘col5’] = df1_1.col5.astype(‘str’)
df1_1.col2.str.cat(df1_1.col5,sep=‘_’)
【MySQL1】
select concat(col2,‘‘,col5)as col9 from t1;
【MySQL2】
select concat_ws(’
’,col2,col5)as col9 from t1;
结果image.pngimage.png

多个字段(含空值)拼接-concat/concat_ws
当字段含有空值时,concat()返回null,而concat_ws()返回非空值部分的拼接。
使用两个非空值字段的三个方法(如下)结果也有所差异,使用+str.cat()的结果都是返回null(如下【Python1】和【Python2】),使用apply()+lambda则将空值处理为nan,全部字段拼接起来(如下【Python3】)。
【Python1】和【Python2】实现了concat()的效果,但是【Python3】和concat_ws()不完全等同。如果要实现concat_ws()的效果,可以在【Python3】的基础上加一步替换值的处理,如【Python4】,加上.apply(lambda x:x.replace('_nan',''))_nan替换为空字符串。

语言PythonMySQL
代码【Python1】
df1_1 = df1.copy()
df1_1[‘col5’] = df1_1.col5.astype(‘str’)
df1_1.col2+‘‘+df1_1.col5+’’+df1_1.col3
【Python2】
df1_1 = df1.copy()
df1_1[‘col5’] = df1_1.col5.astype(‘str’)
df1_1.col2.str.cat([df1_1.col5,df1_1.col3],sep=‘‘)
【Python3】
df1_1 = df1.copy()
df1_1[‘col5’] = df1_1.col5.astype(‘str’)
df1_1[‘col3’] = df1_1.col3.astype(‘str’)
df1_1.apply(lambda x:x.col2+’
’+x.col5+‘‘+x.col3,axis=1)
【Python4】
df1_1 = df1.copy()
df1_1[‘col5’] = df1_1.col5.astype(‘str’)
df1_1[‘col3’] = df1_1.col3.astype(‘str’)
df1_1.apply(lambda x:x.col2+’
’+x.col5+‘_’+x.col3,axis=1)\
.apply(lambda x:x.replace(‘_nan’,‘’))
select concat(col2,‘‘,col5,’’,col3) f_concat,concat_ws(‘_’,col2,col5,col3) f_concat_ws from t1;
结果【Python1和Python2结果】
image.png
【Python3结果】
image.png
【Python4结果】
image.png
image.png

group_concat(多行合并为一行)

MySQL 的group_concat()函数一般用于将多行数据聚合为一行数据。在聚合的过程中,涉及到几种不同的情况,下面逐一看看。

单字段(字符串)聚合,无排序
注意这里有几个限定条件,必须是字符串字段。Python 里没有隐式转换,如果非字符串,需要转化数据类型。转化方式参考concat(),使用astype()进行转化。

语言PythonMySQL
代码【Python1】
df2 = df1.groupby(‘col2’).apply(lambda x:‘,’.join(x.col6)).reset_index().rename(columns={0:‘col6’})
df2
【Python2】
df1.groupby(“col2”).agg({“col6”: lambda x: ‘,’.join(x)}).reset_index()
select col2,group_concat(col6 separator ‘,’) col6 from t1 group by col2;
结果image.pngimage.png

聚合和排序为同一字段
当有排序时,不管聚合字段和排序字段是不是同个字段,在 MySQL 中加一个 order by 子句加上字段即可。
不过在 Python 的实现上二者有一些差异,同一字段时,可以在聚合的时候对列字段进行排序(如下 Python 代码)。

语言PythonMySQL
代码df1.groupby(“col2”).agg({“col6”: lambda x: ‘,’.join(sorted(x, reverse=True))}).reset_index()select col2,group_concat(col6 order by col6 desc separator ‘,’) col6 from t1 group by col2;
结果image.pngimage.png

聚合和排序为不同字段
当聚合字段和排序字段为不同字段时,就不可以使用上面的方法实现了,需要提前对数据排好序,再进行聚合(如下 Python 代码)。其实该语法通用性较好,同一字段也可以使用该语法,改一下排序的字段即可。

语言PythonMySQL
代码df1.sort_values(by=[‘col5’],ascending=False).groupby(“col2”).agg({“col6”: lambda x: ‘,’.join(x)}).reset_index() # 先排序,再聚合。第二排序默认indexselect col2,group_concat(col6 order by col5 desc separator ‘,’) col6 from t1 group by col2;
结果image.pngimage.png

去重聚合,聚合和排序必须为同一字段
去重聚合在 Python 中,可以看作是去重+同字段聚合排序的集合体,先去重,然后根据同一字段聚合排序的逻辑聚合起来。

语言PythonMySQL
代码【Python1】
df1[[‘col2’,‘col6’]].drop_duplicates().sort_values(by=[‘col6’],ascending=False).groupby(“col2”).agg({“col6”: lambda x: ‘,’.join(x)}).reset_index()
【Python2】
df1.sort_values(by=[‘col6’],ascending=False).groupby(“col2”).agg({‘col6’:‘unique’}).agg({“col6”: lambda x: ‘,’.join(x)}).reset_index()
【Python3】
df1.sort_values(by=[‘col6’],ascending=False).groupby(“col2”).agg({‘col6’:‘unique’})[‘col6’].apply(lambda x:‘,’.join(x)).reset_index()
select col2,group_concat(distinct col6 order by col6 desc separator ‘,’) col6 from t1 group by col2;
结果image.pngimage.png

多字段拼接并聚合
多字段拼接并聚合本质上就是使用concat()+group_concat() 进行实现。

语言PythonMySQL
代码df1_1 = df1.copy()
df1_1[‘col5’] = df1_1.col5.astype(‘str’)
df1_1.groupby(‘col2’).apply(lambda x:‘,’.join(x.col6+‘_’+x.col5)).reset_index().rename(columns={0:‘col6’})
select col2,group_concat(concat(col6,‘_’,col5) order by col6 separator ‘,’) col6 from t1 group by col2;
结果image.pngimage.png

一列拆分为多列

一列拆为多列,一般是在某一列有某些特征明显的数据规律,然后通过这些规律将数据拆开,变成多个列。在 MySQL 中,像t3.col9是有多个值通过逗号连在一起,这时候可以通过substring_index()识别逗号进行拆分(如下 MySQL 代码)。
在 Python 中,可以直接使用apply(pd.Series,index=['col_1','col_2','col_3'])实现对应的效果,然后再用pandas.concat()把需求字段拼接返回,如下【Python1】。当然,也可以使用类似 MySQL 的逻辑,分别处理每一个列,将df3.col9使用str.split()拆分开,然后通过索引分别取值,如下【Python2】

语言PythonMySQL
代码【Python1】
df1_1 = df3.col9.apply(lambda x:x.split(‘,’)).apply(pd.Series,index=[‘col_1’,‘col_2’,‘col_3’])
pd.concat([df3.col2,df1_1],axis=1)
【Python2】
df3_1 = df3.copy()
df3_1[‘col_1’]=df3.col9.map(lambda x:x.split(‘,’)[0])
df3_1[‘col_2’]=df3.col9.map(lambda x:x.split(‘,’)[1])
df3_1[‘col_3’]=df3.col9.map(lambda x:x.split(‘,’)[2])
df3_1[[‘col2’,‘col_1’,‘col_2’,‘col_3’]]
select col2,substring_index(col9,‘,’,1)col_1,substring_index(substring_index(col9,‘,’,-1),‘,’,-1)col_2,substring_index(col9,‘,’,-1)col_3 from t3;
结果image.pngimage.png

一行拆分为多行

一行拆分多行和一列拆分多列从字面上看都是一变多的逻辑,不过实现过程大不同。在 MySQL 中,需要借助一个连续增加的列来实现增加行的效果,然后针对每一行再对拆分后的字段进行取舍,如下 MySQL 代码。
在 Python 中,有一个专门将列表数据沿行向展开接口:pandas.explode()。只要将目标列的数据处理成列表的结构,便可直接使用它进行转化,如下 Python 代码。

语言PythonMySQL
代码pd.concat([df3.col2,df3.col9.apply(lambda x:x.split(‘,’))],axis=1).explode(“col9”)select t3.col2,substring_index(substring_index(t3.col9,‘,’,t1.col1),‘,’,-1) col9
from t3
join t1 on t1.col1<=length(t3.col9)-length(replace(t3.col9,‘,’,‘’))+1
结果image.pngimage.png

多行转为多列

多行转多列,在 MySQL 中,通常是通过max(case when)+group by实现,具体语法如下 MySQL 代码。
在 Python 中,则可以使用透视表方法pivot_table()实现。

语言PythonMySQL
代码pd.pivot_table(df1, values=‘col5’, index=[‘col6’],columns=[‘col2’], aggfunc=np.max).reset_index()select col6,max(case when col2=‘AA’ then col5 end) “AA”,max(case when col2=‘BB’ then col5 end) “BB” from t1 group by col6;
结果image.pngimage.png

多列转为多行

多列转多行,在 MySQL 中,其实就是将多列合并为一列,再通过一行转多行实现,即多列转为多行=多列转一列+一行拆分为多行(参考上文和以下 MySQL 代码)。
而 Python 中,有更多的实现方法,如下【Python1】,通过melt()方法便可直接将列值拍平,降维返回。如下【Python2】,通过stack()也可以实现相同的效果。二者不同点在于stack()是对所有的字段进行操作,所以需要把要保留的字段设置为索引,并只取需要拍平的列进行操作,而melt()更简便,直接指定对应的字段即可。
除了这两种方法,还可以使用和 MySQL 代码相同的逻辑,通过先拼接列再拆分行进行处理(如下【Python3】)

语言PythonMySQL
代码【Python1】
df2.melt(id_vars=[‘col2’], value_vars=[‘col4’, ‘col7’],var_name=‘指标’, value_name=‘指标值’) # ignore_index=False不重置索引,默认重置
【Python2】
df2.set_index(‘col2’).stack().reset_index().rename(columns={‘level_1’:‘指标’,0:‘指标值’})
【Python3】
df2_1 = df2.copy()
df2_1[‘col4’] = df2_1.col4.astype(‘str’)
df2_1[‘col7’] = df2_1.col7.astype(‘str’)
df2_target = pd.concat([df2_1.col2,pd.Series([‘col4,col7’]*3).apply(lambda x:x.split(‘,’))],axis=1).explode(0).rename(columns={‘col2’:‘col’,0:‘指标’})
df2_value = pd.concat([df2_1.col2,df2_1.apply(lambda x:x.col4+‘,’+x.col7,axis=1).apply(lambda x:x.split(‘,’))],axis=1).explode(0).rename(columns={0:‘指标值’})
pd.concat([df2_target,df2_value],axis=1)[[‘col2’,‘指标’,‘指标值’]]
select t2.col2,if(t1.col1=1,‘col4’,‘col7’) “指标”,substring_index(substring_index(concat(t2.col4,‘,’,t2.col7),‘,’,t1.col1),‘,’,-1) “指标值”
from t2
join t1 on t1.col1<=2
结果image.pngimage.png

三、小结

MySQL 和 Python 在处理行列转化时,灵活性都很强。二者相比较之下,Python 会略胜一筹,它提供更多的接口,可以辅助我们更加灵活地处理数据,实现预期效果。不过,MySQL 相对会更简洁一些,格式比较统一,语法也比较简单。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/161523.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Linux】make/Makefile的简单使用

人生的态度是&#xff0c;抱最大的希望&#xff0c;尽最大的努力&#xff0c;做最坏的打算。 – 柏拉图 《理想国》 目录一.Linux项目自动化构建工具-make/Makefile1.为什么需要使用make/Makefile2.简单理解make和Makefile3.如何编写Makefile文件3.1生成可执行程序&#xff1a…

智算中心掀落地热潮,加速AI普惠化

11日&#xff0c;国家信息中心与浪潮信息联合发布的《智能计算中心创新发展指南》显示&#xff0c;目前全国有超过30个城市正在建设或提出建设智算中心&#xff0c;“十四五”期间&#xff0c;对智算中心的投资可带动人工智能核心产业增长约2.9-3.4倍。 《科创板日报》记者注意…

python+人脸识别+opencv实现真实人脸驱动的阿凡达(中)

目录一、前言二、消除图片拼接缝隙三、基于一张图片正脸转侧脸的实现1、人体头部的二维成像知识2、用特征点驱动的方法实现侧脸2.1python核心代码三、后续工作一、前言 我们在上篇名叫python人脸识别opencv实现真实人脸驱动的阿凡达&#xff08;上博文里已经实现了基于三角映射…

教资报名啦 有问题欢迎评论区提问~

报考小tips&#xff1a; ①一次选报你所有准备报考的学科 ②看好类别&#xff0c;有些是“音体美专业”专属 ③审核前如果发现有漏报的科目&#xff0c;可以先取消再报 ④一旦审核通过&#xff0c;就不能更改/增加/较少报考科目 ⑤缴费成功后&#xff0c;不退费【如果考试前几天…

德云社、本山传媒齐聚辽宁卫视春晚,郭德纲和本山大叔会参加吗

腊月二十九&#xff0c;屋里走。不得不说辽宁卫视会选时间&#xff0c;兔年的春晚定在了农历腊月二十九这一天。备受关注的辽宁卫视春晚&#xff0c;准备在农历的腊月二十九晚上七点三十分&#xff0c;正式与广大观众见面。 辽宁卫视春晚之所以倍受期待&#xff0c;是因为这些年…

【MySQL】深入理解MySQL事务(上篇)

MySQL事务前言事务的ACID 特性事务提交方式事务常见操作方式正常演示 - 证明事务的开始与回滚非正常演示1 - 证明未commit&#xff0c;客户端崩溃&#xff0c;MySQL自动会回滚&#xff08;隔离级别设置为读未提交&#xff09;非正常演示2 - 证明commit了&#xff0c;客户端崩溃…

2021年大数据挑战赛A题智能运维中的异常检测与趋势预测求解全过程论文及程序

2021年大数据挑战赛 A题 智能运维中的异常检测与趋势预测 原题再现&#xff1a; 异常检测&#xff08;异常诊断/发现&#xff09;、异常预测、趋势预测&#xff0c;是智能运维中首当其冲需要解决的问题。这类问题是通过业务、系统、产品直接关联的 KPI 业务指标进行分析诊断&…

【Linux】生产者消费者

生产者消费者 生产者消费者问题概述 生产者/消费者问题&#xff0c;也被称作有限缓冲问题。可以描述为&#xff1a;两个或者更多的线程共享同一个缓冲 区&#xff0c;其中一个或多个线程作为“生产者”会不断地向缓冲区中添加数据&#xff0c;另一个或者多个线程作为“消费者”…

优先级队列--堆的应用(堆排序与TopK问题)

堆排序&#xff1a;比较方式为小于建大堆 priority_queue(Iterator first, Iterator last): _con(first, last) // 1、使用vector的区间构造函数来初始化_con{// 2、建堆&#xff1a;从完全二叉树的最后一个非叶子结点来进行向下调整for (int i (size() - 2) / 2; i > 0; i…

2023真无线蓝牙耳机怎么选?值得入手的蓝牙耳机推荐

蓝牙耳机作为近几年备受人们欢迎的数码产品&#xff0c;很多人都想买到一款适合自己的蓝牙耳机。但&#xff0c;随着蓝牙耳机的快速发展&#xff0c;蓝牙耳机市场充斥着各种机型&#xff0c;它们有着不同的性能、价格、外观等。所以&#xff0c;不少人都有一个疑惑&#xff0c;…

玩转 MySQL Shell 沙盒实例

什么是沙盒实例&#xff1f; 沙盒实例仅适用于出于测试目的在本地计算机上部署和运行&#xff0c;可以与 InnoDB Cluster 、 InnoDB ClusterSet 和 InnoDB ReplicaSet 一起工作。 如何使用部署沙盒的 API 函数&#xff1f; 语法dba.deploySandboxInstance(port[, options])解…

Mybatis学习笔记(一)

什么是框架&#xff1f; 它是我们软件开发中的一套解决方案&#xff0c;不同的框架解决的是不同的问题使用框架的好处&#xff1a;框架封装了很多的细节&#xff0c;使开发者可以使用极简的方式实现功能&#xff0c;大大提高开发效率 三层架构 表现层&#xff1a;用于展示数…

慕尼黑工业大学开源含四季的数据集:用于自动驾驶的视觉长期定位

以下内容来自[从零开始机器人SLAM知识星球] 每日更新内容 点击领取学习资料 → 机器人SLAM学习资料大礼包 #论文# #开源数据集# 4Seasons: Benchmarking Visual SLAM and Long-Term Localization for Autonomous Driving in Challenging Conditions 地址&#xff1a;https:/…

LeetCode[295]数据流的中位数

难度:困难题目&#xff1a;中位数是有序整数列表中的中间值。如果列表的大小是偶数&#xff0c;则没有中间值&#xff0c;中位数是两个中间值的平均值。例如 arr [2,3,4] 的中位数是 3 。例如 arr [2,3] 的中位数是 (2 3) / 2 2.5 。描述&#xff1a;实现 MedianFinder 类:…

工信部及多地政府联合阿里健康在全国展开防疫保供专项行动

为了切实服务好百姓的购药需求&#xff0c;在工信部和各地政府的指导下&#xff0c;12月疫情政策调整以来&#xff0c;阿里健康已先后在全国20多个省市及地区配合药品物资精准投放工作&#xff0c;为各地居民重点供退热药、N95口罩等紧缺药品和物资&#xff0c;尽全力打好药品保…

Android系统定制开发过程快速查找定位分析代码的方法

推荐阅读 ​Android系统开发过程快速查找定位代码的方法 Android10以上系统定制Root权限(隐藏Root权限) 商务合作 2023年招聘 2023年逆向分析资料汇总 Android系统开发过程&#xff0c;经常需要进行文件查找、代码查找&#xff0c;常用find和grep查找命令 1.find命令 根据文…

短短六年时间冲到二奢品类第一,妃鱼如何做到的?

随着消费需求不断增长&#xff0c;二手奢侈品市场近五年来快速向规模化、平台化发展&#xff0c;妃鱼、红布林、胖虎等二奢电商品牌迅速崛起&#xff0c;成为风头劲胜的网红。国泰君安研究报告显示&#xff0c;中国闲置高端消费品零售市场规模已从2016年162亿元增长至2020年的5…

Vue js混淆加密 webpack-obfuscator

公司要求加密混淆js 之前 是用的glifyjs-webpack-plugin ,感觉不行。 然后使用了webpack-obfuscator 非常nice~&#xff0c;除了打包出来体积会有点大&#xff0c;浏览的网页会变慢&#xff0c;选择最低是就还好&#xff0c; 有多个条件属性可以选择&#xff0c; 可以选择高度混…

networkx学习(三) 随机网络

networkx学习(三) 随机网络 1.规则网络 2.随机网络的生成算法 第一种:G(N,L) import random import itertoolsdef GNL(N, L):G = nx.Graph()G.

硬盘数据如何恢复?电脑硬盘资料恢复,方法就是这么简单!

硬盘作为重要的存储设备&#xff0c;里面保存的数据是很重要的。日常生活和工作中&#xff0c;硬盘发生数据丢失也是很常见的事情&#xff0c;比如&#xff1a;误删重要文件并清空了回收站、文件打不开提示格式化、分区变成RAW格式、电脑重新分区等。各种数据丢失原因数不胜数。…