数据科学库Python——Pandas数据合并与分组聚合_2(join和merge)

目录

一、数据合并之join

二、数据合并之merge

 (1)连接键 on

 (2)索引连接 lef/right_index

三、应用实例

 分组与聚合

调用聚合方法

问题:统计中国每个省店铺的数量。

问题:数据按照多个条件进行分组。

复合索引

修改index

重新设定index

指定某一列为index

 返回index的唯一值df.index.unique()

复合索引

Demo1

Demo2


一、数据合并之join

join:默认情况下他是把行索引相同的数据合并到一起

二、数据合并之merge

pd.merge(left, right, how='inner', on=None, left_on=None, right_on=None,
         left_index=False, right_index=False, sort=True,
         suffixes=('_x', '_y'), copy=True, indicator=False,
         validate=None)

参数如下:

  • left: 拼接的左侧DataFrame对象
  • right: 拼接的右侧DataFrame对象
  • on: 要加入的列或索引级别名称。 必须在左侧和右侧DataFrame对象中找到。 如果未传递且left_index和right_index为False,则DataFrame中的列的交集将被推断为连接键。
  • left_on:左侧DataFrame中的列或索引级别用作键。 可以是列名,索引级名称,也可以是长度等于DataFrame长度的数组。
  • right_on: 左侧DataFrame中的列或索引级别用作键。 可以是列名,索引级名称,也可以是长度等于DataFrame长度的数组。
  • left_index: 如果为True,则使用左侧DataFrame中的索引(行标签)作为其连接键。 对于具有MultiIndex(分层)的DataFrame,级别数必须与右侧DataFrame中的连接键数相匹配。
  • right_index: 与left_index功能相似。
  • how: One of ‘left’, ‘right’, ‘outer’, ‘inner’. 默认inner。inner是取交集,outer取并集。比如left:[‘A’,‘B’,‘C’];right[’'A,‘C’,‘D’];inner取交集的话,left中出现的A会和right中出现的买一个A进行匹配拼接,如果没有是B,在right中没有匹配到,则会丢失。'outer’取并集,出现的A会进行一一匹配,没有同时出现的会将缺失的部分添加缺失值。
  • sort: 按字典顺序通过连接键对结果DataFrame进行排序。 默认为True,设置为False将在很多情况下显着提高性能。
  • suffixes: 用于重叠列的字符串后缀元组。 默认为(‘x’,’ y’)。
  • copy: 始终从传递的DataFrame对象复制数据(默认为True),即使不需要重建索引也是如此。
  • indicator:将一列添加到名为_merge的输出DataFrame,其中包含有关每行源的信息。

 (1)连接键 on

df_1 = pd.DataFrame({'a':[1,2],'x':[5,6]})
df_1

 

df_2 = pd.DataFrame({'a':[2,1,0],'y':[6,7,8]})
df_2

 

 pd.merge(df_1,df_2,on = 'a')

按照a这一列,从左到右进行连接

 (2)索引连接 lef/right_index

可以直接按索引进行连接。

pd.merge(df_1,df_2,left_index = True,right_index = True,suffixes = ("_1","_2"))

 >>>

 本例中,两个表都有同名的a列,用suffixes参数设置后缀来进行区分。

三、应用实例

现在我们有一组关于全球星巴克店铺的统计数据,如果我想知道美国的星巴克数量和中国的哪个多,或者我想知道中国每个省份星巴克的数量的情况,那么应该怎么办?

数据来源:https://www.kaggle.com/starbucks/store-locations/data

查看数据的基本信息:

import pandas as pd
import numpy as np

file_path = "./starbucks_store_worldwide.csv"

df = pd.read_csv(file_path)
print(df.head(1))

 >>>

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 25600 entries, 0 to 25599
Data columns (total 13 columns):
 #   Column          Non-Null Count  Dtype  
---  ------          --------------  -----  
 0   Brand           25600 non-null  object 
 1   Store Number    25600 non-null  object 
 2   Store Name      25600 non-null  object 
 3   Ownership Type  25600 non-null  object 
 4   Street Address  25598 non-null  object 
 5   City            25585 non-null  object 
 6   State/Province  25600 non-null  object 
 7   Country         25600 non-null  object 
 8   Postcode        24078 non-null  object 
 9   Phone Number    18739 non-null  object 
 10  Timezone        25600 non-null  object 
 11  Longitude       25599 non-null  float64
 12  Latitude        25599 non-null  float64
dtypes: float64(2), object(11)
memory usage: 2.5+ MB
None

 分组与聚合

# 分组与聚合
grouped = df.groupby(by = "Country")
grouped
>>>
<pandas.core.groupby.generic.DataFrameGroupBy object at 0x7fc04bfd4370>

.DataFrameGroupBy
可以遍历
调用聚合方法

for i,j in grouped:
    print(i)
    print("-"*100)
    print(j)
    print("*"*100)
AD
----------------------------------------------------------------------------------------------------
       Brand  Store Number     Store Name Ownership Type     Street Address  \
0  Starbucks  47370-257954  Meritxell, 96       Licensed  Av. Meritxell, 96   

               City State/Province Country Postcode Phone Number  \
0  Andorra la Vella              7      AD    AD500    376818720   

                  Timezone  Longitude  Latitude  
0  GMT+1:00 Europe/Andorra       1.53     42.51  
****************************************************************************************************
AE
----------------------------------------------------------------------------------------------------
         Brand  Store Number                      Store Name Ownership Type  \
1    Starbucks  22331-212325                Ajman Drive Thru       Licensed   
2    Starbucks  47089-256771                       Dana Mall       Licensed   
3    Starbucks  22126-218024                      Twofour 54       Licensed   
4    Starbucks  17127-178586                    Al Ain Tower       Licensed   
5    Starbucks  17688-182164        Dalma Mall, Ground Floor       Licensed   
..         ...           ...                             ...            ...   
140  Starbucks   34253-62541                  Bukhatir Tower       Licensed   
141  Starbucks   1359-138434                  Qanat Al Qasba       Licensed   
142  Starbucks   34259-54260                   Sahara Center       Licensed   
143  Starbucks   34217-27108  American University of Sharjah       Licensed   
144  Starbucks  22697-223524                  UAQ Drive Thru       Licensed   

                         Street Address           City State/Province Country  \
1                  1 Street 69, Al Jarf          Ajman             AJ      AE   
2          Sheikh Khalifa Bin Zayed St.          Ajman             AJ      AE   
3                       Al Salam Street      Abu Dhabi             AZ      AE   
4       Khaldiya Area, Abu Dhabi Island      Abu Dhabi             AZ      AE   
5                  Dalma Mall, Mussafah      Abu Dhabi             AZ      AE   
..                                  ...            ...            ...     ...   
140            Sharjah Buheira Corniche        Sharjah             SH      AE   
141                      Al Taawun Road        Sharjah             SH      AE   
142                             Alnahda        Sharjah             SH      AE   
143  Airport Road, Universities Complex        Sharjah             SH      AE   
144                 King Faisal Highway  Umm Al Quwain             UQ      AE

 按照Country来分组,将相同Country的数据放到一起,成为一个DataFrame。

另一种方式:

df[df["Copuntry"] = "US"]

 

 这里的length就是我们想要的结果,即美国有13608家Starbucks.

调用聚合方法

grouped.count()

 grouped["Brand"].count()

 >>>

country_count = grouped["Brand"].count()
print(country_count["US"])
print(country_count["CN"])

 >>>

13608

2734

 问题:统计中国每个省店铺的数量。

china_data = df[df["Country"] == "CN"]
grouped = china_data.groupby(by = "State/Province").count()["Brand"]
print(len(grouped.index))
print(grouped.index)

>>>

length = 31
State/Province
11    236
12     58
13     24
14      8
15      8
21     57
22     13
23     16
31    551
32    354
33    315
34     26
35     75
36     13
37     75
41     21
42     76
43     35
44    333
45     21
46     16
50     41
51    104
52      9
53     24
61     42
62      3
63      3
64      2
91    162
92     13
Name: Brand, dtype: int64

 总结:

china_data = df[df["Country"] == "CN"]
grouped = china_data.groupby(by = "State/Province")

抽象为:

grouped = df.groupby(by = "columns_name")

grouped是一个DataFrameGroupBy对象,是可迭代的。

grouped中的每一个元素是一个元组

元组里面的内容结构为:【索引(按照Country分组,对应分组的值),分组之后的DataFrame】

DataFrameGroupBy对象有很多经过优化的方法。

问题:数据按照多个条件进行分组。

根据国家省份进行分组。

相当于两个索引,一个索引为Country,另一个为State/Province

df["Brand"].groupby(by = ["Country","State/Province"])

这个有问题吗?

不能直接按照两个同时分组。

# 正确的分组方法
grouped = df["Brand"].groupby(by = [df["Country"],df["State/Province"]]).count()
print(grouped)
>>>

type:<class 'pandas.core.series.Series'>

这个结果有两个索引,Country和State/Province

 但是这个不包含列名"Brand",所以是个Series类型。

需要强调的是,Series类型的数据是index+value一一对应的。不存在columns。

 可以对比一下这两种

        前者是df["Brand"].groupby(by = "  "),最后的结果是Series类型,index+value一一对应。

        后者是df[["Brand"]].groupby(by = "  "),最后的结果是DataFrame类型,既有索引和Columns。

第一个就是按照这个列名去里面取,第二个取出来的结果是带着列名的。

还有另外的方法2:

grouped_1 = df.groupby(by =[df["Country"],df["State/Province"]])[["Brand"]].count()
grouped_1

>>>输出类型是DataFrame,如果要Series就去掉一个[ ]

 还有另外的方法3:

当前两列都是index,因为按照两个条件进行分组的,即复合索引

复合索引

修改index

 

重新设定index

df.reindex

 里面传入的参数是一个list

指定某一列为index

基础语法为:df.set_index("key",drop = True/False)

里面默认为True,表示把key这一列拿去当索引,然后key就移出去了。

 

传入参数:drop=False

目的:我们想仍旧保留key这一列

 返回index的唯一值df.index.unique()

这个unique的输出结果是一个可迭代对象,可以遍历,可以转成list、tuple都可。

查看索引的内容:

复合索引

一、如果要进行索引的数据是Series类型,可以用两种方式。

(1)df["Columns1"]["Columns2"]

(2)df.loc["Columns"].loc["Columns2"]

二、如果要进行索引的数据是DataFrame类型,就用loc来索引

需要注意的是,如下的操作是去“A”这一列,并非通过索引取值。

取完后的这个值是一个Series类型。

对于DataFrame的复合索引问题,我们可以用到loc操作。

 

 ### swap方法

Demo1

1. 使用 matplotlib 呈现出店铺总数排名前 10 的国家
2. 使用 matplotlib 呈现出每个中国每个城市的店铺数量

 

 

 

from matplotlib import font_manager
my_font = font_manager.FontProperties(fname="/System/Library/Fonts/PingFang.ttc")
_x_ = data_2.index
_y_ = data_2.values
# 画图
plt.figure(figsize = (20,12),dpi = 80)
plt.barh(range(len(_x_)),_y_)
plt.yticks(range(len(_x_)),_x_,fontproperties = my_font)
plt.show()

 >>>

Demo2

现在我们有全球排名靠前的10000本书的数据,那么请统计一下下面几个问题:
1.不同年份书的数量
2.不同年份书的平均评分情况
收据来源:https://www.kaggle.com/zygmunt/goodbooks-10k

import numpy as np
import pandas as pd
file_path = './books.csv'
df = pd.read_csv(file_path)
df.head(1)

 

 

 

# 2.不同年份书的平均评分情况
groupedd = data_1["average_rating"].groupby(by = data_1["original_publication_year"]).mean()
print(groupedd)
__x = groupedd.index
__y = groupedd.values
plt.figure(figsize = (20,8),dpi = 80)
plt.plot(range(len(__x)),__y)
plt.xticks(list(range(len(__x)))[::10],__x[::10].astype(int),rotation=45)
plt.show()
print(__y)

 

 

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值