对比MySQL,学会在Pandas中实现SQL的常用操作

举报
yd_226342373 发表于 2021/05/25 04:10:14 2021/05/25
【摘要】 本文说明 我相信你如果学习了Pandas,就一定是想从事数据分析这样一个行业。既然你想从事数据分析行业,那我就默认你肯定是会Sql,即使你现在不会,你以后也要会。 本文旨在对比Sql,说明如何使用Pandas中执行各种SQL操作。真的!好像对比起来,学习什么都快了。 本文大纲 导入相关库和数据读取 import numpy as np import pa...

本文说明

我相信你如果学习了Pandas,就一定是想从事数据分析这样一个行业。既然你想从事数据分析行业,那我就默认你肯定是会Sql,即使你现在不会,你以后也要会。

本文旨在对比Sql,说明如何使用Pandas中执行各种SQL操作。真的!好像对比起来,学习什么都快了。
在这里插入图片描述

本文大纲

在这里插入图片描述

导入相关库和数据读取

import numpy as np
import pandas as pd

df = pd.read_csv("tips.csv",encoding="gbk")
df.head()

  
 
  • 1
  • 2
  • 3
  • 4
  • 5

结果如下:
在这里插入图片描述

1.Select数据查询

在SQL中,选择是使用您要选择的列(用逗号分隔)或(*选择所有列)来完成的。

SELECT '总费用', '小费', '是否吸烟', '吃饭时间'
FROM df
LIMIT 5;

  
 
  • 1
  • 2
  • 3

对于pandas,通过将列名列表传递给DataFrame来完成列选择。

df[['总费用', '小费', '是否吸烟', '吃饭时间']].head(5)

  
 
  • 1

结果如下:
在这里插入图片描述
注意:调用不带列名列表的DataFrame将显示所有列(类似于SQL的 *)。

在SQL中,您可以添加一个计算列

SELECT *, "小费"/"总费用" as "小费占比"
FROM df
LIMIT 5;

  
 
  • 1
  • 2
  • 3

对于pandas,可以使用DataFrame.assign()的方法追加新列。

df.assign(小费占比=df['小费'] / df['总费用']).head(5)

  
 
  • 1

结果如下:
在这里插入图片描述

2.Where按条件查询

通过WHERE子句在SQL中进行过滤。

SELECT *
FROM df
WHERE 吃饭时间 = '晚餐'
LIMIT 5;

  
 
  • 1
  • 2
  • 3
  • 4

DataFrame可以通过多种方式进行过滤。最直观的方法是使用布尔索引

df[df['吃饭时间'] == '晚餐'].head(5)

  
 
  • 1

结果如下:
在这里插入图片描述
上面的语句只是将Series的True / False对象传递给DataFrame,并返回所有带有True的行。

is_dinner = df['吃饭时间'] == '晚餐'
is_dinner.value_counts()
df[is_dinner].head(5)

  
 
  • 1
  • 2
  • 3

结果如下:
在这里插入图片描述
就像SQL的OR和AND一样,可以使用|将多个条件传递给DataFrame。|(OR)和&(AND)。

SELECT *
FROM df
WHERE 吃饭时间 = '晚餐' AND 小费 > 5.00;

  
 
  • 1
  • 2
  • 3

那么,在DataFrame代码应该怎么写呢?

df[(df['吃饭时间'] == '晚餐') & (df['小费'] > 5.00)]

  
 
  • 1

结果如下:
在这里插入图片描述

3.in和not in条件查询

我们先来看看在SQL中应该怎么做。

SELECT *
FROM df
WHERE 星期几 in (周四,周五)
LIMIT 5;

  
 
  • 1
  • 2
  • 3
  • 4

对比到DataFrame中,我们再看看怎么做?

df[df["星期几"].isin(['周四','周五'])].head(5)

  
 
  • 1

结果如下:
在这里插入图片描述
如果是not in,对比到DataFrame中,直接使用取反操作(~)。

df[~df["星期几"].isin(['周四','周五'])].head(5)

  
 
  • 1

结果如下:
在这里插入图片描述

4.group by分组统计

在Pandas中,SQL的GROUP BY操作是使用类似命名的groupby()方法执行的。 groupby()通常是指一个过程,在该过程中,我们希望将数据集分成多个组,应用某些功能(通常是聚合),然后将各组组合在一起。

常见的SQL操作是获取整个数据集中每个组中的记录数。例如,通过查询可以了解性别留下的提示数量。

SELECT "性别", count(*)
FROM df
GROUP BY 性别;

  
 
  • 1
  • 2
  • 3

对比到DataFrame中,应该是这样的。

df.groupby('性别').size()

  
 
  • 1

结果如下:
在这里插入图片描述
注意,在pandas代码中我们使用了size()而不是count()。这是因为count()将函数应用于每一列,并返回每一列中的记录数。

df.groupby('性别').count()

  
 
  • 1

结果如下:
在这里插入图片描述
如果想要使用count()方法应用于单个列的话,应该这样做。(后面需要随意选择一列)

df.groupby('性别')["总费用"].count()

  
 
  • 1

结果如下:
在这里插入图片描述
也可以一次应用多种功能。例如,假设我们要查看小费金额在一周中的各个天之间有何不同—>agg()允许您将字典传递给分组的DataFrame,从而指示要应用于特定列的函数。

在SQL中:

SELECT 星期几, AVG(小费), COUNT(*)
FROM df
GROUP BY 星期几;

  
 
  • 1
  • 2
  • 3

在Dataframe中:

df.groupby('星期几').agg({'小费': np.mean, '星期几': np.size})

  
 
  • 1

结果如下:
在这里插入图片描述
通过将一列列传递给方法,来完成按多个列分组groupby()。在SQL中:

SELECT 是否吸烟, 星期几, COUNT(*), AVG(小费)
FROM tips
GROUP BY 是否吸烟, 星期几;

  
 
  • 1
  • 2
  • 3

在Dataframe中:

df.groupby(['是否吸烟', '星期几']).agg({'小费': [np.size, np.mean]})

  
 
  • 1

结果如下:
在这里插入图片描述

5.join数据关联

可以使用join()merge()执行JOIN。 默认情况下,join()将在其索引上联接DataFrame。 每个方法都有参数,可让您指定要执行的联接类型(LEFT,RIGHT,INNER,FULL)或要联接的列(列名或索引)。但是还是推荐使用merge()函数。

1)数据准备

df1 = pd.DataFrame({'key': ['A', 'B', 'C', 'D'], 'value': [1, 3, 5, 7]})

df2 = pd.DataFrame({'key': ['B', 'D', 'D', 'E'], 'value':[2, 4, 6, 8]})

  
 
  • 1
  • 2
  • 3
  • 4
  • 5

结果如下:
在这里插入图片描述
假设我们有两个数据库表,它们的名称和结构与我们的DataFrames相同。现在让我们看一下各种类型的JOIN。

2)inner join内连接

在SQL中:

SELECT *
FROM df1
INNER JOIN df2
  ON df1.key = df2.key;

  
 
  • 1
  • 2
  • 3
  • 4

在Dataframe中:

pd.merge(df1, df2, on='key')

  
 
  • 1

结果如下:
在这里插入图片描述

3)left outer join左连接

在SQL中:

SELECT *
FROM df1
LEFT OUTER JOIN df2
  ON df1.key = df2.key;

  
 
  • 1
  • 2
  • 3
  • 4

在Dataframe中:

pd.merge(df1, df2, on='key', how='left')

  
 
  • 1

结果如下:
在这里插入图片描述

4)right join右连接

在SQL中:

SELECT *
FROM df1
RIGHT OUTER JOIN df2
  ON df1.key = df2.key;

  
 
  • 1
  • 2
  • 3
  • 4

在Dataframe中:

pd.merge(df1, df2, on='key', how='right')

  
 
  • 1

结果如下:
在这里插入图片描述

5)full join全连接

注意在MySQL中是不支持全连接的,一般是使用union完成这个操作的,这将在下面一个知识点中讲述。

在Dataframe中:

pd.merge(df1, df2, on='key', how='outer')

  
 
  • 1

结果如下:
在这里插入图片描述

6、union数据合并

UNION (ALL)操作在Dataframe中可以使用concat()来执行。

1)数据准备

df1 = pd.DataFrame({'city': ['Chicago', 'San Francisco', 'New York City'], 'rank': range(1, 4)}) df2 = pd.DataFrame({'city': ['Chicago', 'Boston', 'Los Angeles'], 'rank': [1, 4, 5]})

  
 
  • 1
  • 2
  • 3
  • 4
  • 5

结果如下:
在这里插入图片描述

2)union all不去重合并

在SQL中:

SELECT city, rank
FROM df1
UNION ALL
SELECT city, rank
FROM df2;

""" city rank Chicago 1
San Francisco 2
New York City 3 Chicago 1 Boston 4
  Los Angeles 5
"""

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

在Dataframe中:

# 默认就是axis=0
pd.concat([df1, df2],axis=0)

  
 
  • 1
  • 2

结果如下:
在这里插入图片描述

3)union去重合并

在SQL中:

SELECT city, rank
FROM df1
UNION
SELECT city, rank
FROM df2;
-- notice that there is only one Chicago record this time

""" city rank Chicago 1
San Francisco 2
New York City 3 Boston 4
  Los Angeles 5
"""

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

在Dataframe中:

pd.concat([df1, df2]).drop_duplicates()

  
 
  • 1

结果如下:
在这里插入图片描述

7.取group分组后的Topn

在MySQL8.0以前的版本,可能是不支持窗口函数,因此求Topn可能有些费劲,以前的文章中已经讲述过,这里也就不在赘述。

有下面一堆数据,怎么求出Topn呢?

df = pd.DataFrame({"name":["张三","王五","李四","张三","王五","张三","李四","李四","王五"], "subject":["语文","英语","数学","数学","语文","英语","语文","英语","数学"], "score":[95,80,83,80,90,71,88,70,78]})
df

  
 
  • 1
  • 2
  • 3
  • 4

结果如下:
在这里插入图片描述
在Dataframe中:

df.groupby(["subject"]).apply(lambda df:df.sort_values("score",ascending=True))

  
 
  • 1

结果如下:
在这里插入图片描述

文章来源: blog.csdn.net,作者:数据分析与统计学之美,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/weixin_41261833/article/details/107377968

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。