Python_数据科学库_数据的合并与分组聚合

这篇博客详细介绍了Python中数据合并的方法,包括join和merge,并解释了如何使用on和how参数。此外,还讨论了如何在DataFrame上进行分组操作,如计算统计指标。最后,提到了简单的索引和复合索引操作,如设置和重置索引。

1 数据合并之join

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

在这里插入图片描述

import pandas as pd
import numpy as np
df1 = pd.DataFrame(np.ones((2,4)),index=['A','B'],columns=list('abcd'))
df2 = pd.DataFrame(np.zeros((3,3)),index=['A','B','C'],columns=list('xyz'))
print(df1)
#      a    b    c    d
# A  1.0  1.0  1.0  1.0
# B  1.0  1.0  1.0  1.0
print(df2)
#      x    y    z
# A  0.0  0.0  0.0
# B  0.0  0.0  0.0
# C  0.0  0.0  0.0
df3 = df1.join(df2) #行数以df1为准
print(df3)
#      a    b    c    d    x    y    z
# A  1.0  1.0  1.0  1.0  0.0  0.0  0.0
# B  1.0  1.0  1.0  1.0  0.0  0.0  0.0
df4 = df2.join(df1) #行数以df2为准,df1中的没有值为nan
print(df4)
#      x    y    z    a    b    c    d
# A  0.0  0.0  0.0  1.0  1.0  1.0  1.0
# B  0.0  0.0  0.0  1.0  1.0  1.0  1.0
# C  0.0  0.0  0.0  NaN  NaN  NaN  NaN

2 数据合并之merge

merge:按照指定的列把数据按照一定的方式合并到一起

  • 当两个dataframe具有相同的column时,若两个column中没有相同的value,则会merge一个空的dataframe

  • 直接使用merge合并两个DataFrame, res = pd.merge(left,right) ,不加任何属性参数的情况下,默认是inner合并

  • res = pd.merge(left,right,on=‘key’),当加上on属性的时候,是基于key列来合并,通过key的每一个值来查找左右两边的数据,组成新的DataFrame

  • merge操作实现两个DataFrame之间的合并。merge的使用方法及参数解释如下:

pd.merge(left, right, on=None, how='inner', left_on=None, right_on=None, left_index=False, right_index=False, 
     sort=False, suffixes=('_x', '_y'), copy=True, indicator=False, validate=None)
  • left和right:第一个DataFrame和第二个DataFrame对象,merge只能实现两个DataFrame的合并,无法一次实现多个合并

  • how:合并的方式,默认为inner取参考column的交集,outer取并集保留所有行;outer、left、right中的缺失值都以NaN填充;left按照左边对象为参考进行合并即保留左边的所有行,right按照右边对象为参考进行合并即保留右边所有行,

  • left_on=None和right_on=None:以上on是在两个df有相同的column的情况下使用,如果两个df没有相同的column,使用left_on和right_on分别指明左边和右边的参考column

  • left_index和right_index:指定是否以索引为参考进行合并

  • sort:合并结果是否按on指定的参考进行排序

  • suffixed:合并后如果有重复column,分别加上什么后缀

  • on:指定参考column,如果不指定默认为None,以两者相同列的最多数为参考;index重新生成为从0开始的整数。

import pandas as pd
df1 = pd.DataFrame({'key1':['a','b','c','d'],'key2':['e','f','g','h'],'key3':['i','j','k','l']},index=['k','l','m','n',])
df2 = pd.DataFrame({'key1':['a','B','c','d'],'key2':['e','f','g','H'],'key4':['i','j','K','L']},index = ['p','q','u','v'])
print(df1)
#   key1 key2 key3
# k    a    e    i
# l    b    f    j
# m    c    g    k
# n    d    h    l
print(df2)
#   key1 key2 key4
# p    a    e    i
# q    B    f    j
# u    c    g    K
# v    d    H    L
print(pd.merge(df1,df2,on='key1'))
#   key1 key2_x key3 key2_y key4
# 0    a      e    i      e    i
# 1    c      g    k      g    K
# 2    d      h    l      H    L
print(pd.merge(df1,df2,on='key2'))
#   key1_x key2 key3 key1_y key4
# 0      a    e    i      a    i
# 1      b    f    j      B    j
# 2      c    g    k      c    K
print(pd.merge(df1,df2,on=['key1','key2']))
#   key1 key2 key3 key4
# 0    a    e    i    i
# 1    c    g    k    K
print(pd.merge(df1,df2))  #可以看到不加on参数,系统自动以个数最多的相同column为参考
#   key1 key2 key3 key4
# 0    a    e    i    i
# 1    c    g    k    K
  • how:指定合并方式,如果不指定默认为inner

对于outer、left、right来说可能会出现缺失值,全部以NaN填充。

import pandas as pd
df1 = pd.DataFrame({'key1':['a','b','c','d'],'key2':['e','f','g','h'],'key3':['i','j','k','l']},index=['k','l','m','n',])
df2 = pd.DataFrame({'key1':['a','B','c','d'],'key2':['e','f','g','H'],'key4':['i','j','K','L']},index = ['p','q','u','v'])
print(df1)
#   key1 key2 key3
# k    a    e    i
# l    b    f    j
# m    c    g    k
# n    d    h    l
print(df2)
#   key1 key2 key4
# p    a    e    i
# q    B    f    j
# u    c    g    K
# v    d    H    L
print(pd.merge(df1,df2,how='inner'))   #默认方式,取交集
#   key1 key2 key3 key4
# 0    a    e    i    i
# 1    c    g    k    K
print(pd.merge(df1,df2,how='outer'))   #取并集
#   key1 key2 key3 key4
# 0    a    e    i    i
# 1    b    f    j  NaN
# 2    c    g    k    K
# 3    d    h    l  NaN
# 4    B    f  NaN    j
# 5    d    H  NaN    L
print(pd.merge(df1,df2,how='left'))    #以左边为参考,即保留左边所有行
#   key1 key2 key3 key4
# 0    a    e    i    i
# 1    b    f    j  NaN
# 2    c    g    k    K
# 3    d    h    l  NaN
print(pd.merge(df1,df2,how='right'))   #以右边为参考,即保留右边所有行
#   key1 key2 key3 key4
# 0    a    e    i    i
# 1    c    g    k    K
# 2    B    f  NaN    j
# 3    d    H  NaN    L
  • left_on和right_on:默认都为False,但是如果两个DataFrame没有相同的column而又需要对它们的按列合并,则需要使用left_on和right_on分别指明两边的参考列;index重新生成为从0开始的整数。
import pandas as pd
df1 = pd.DataFrame({'key1':['a','b','c','d'],'key2':['e','f','g','h'],'key3':['i','j','k','l']},index=['k','l','m','n'])
df2 = pd.DataFrame({'key4':['a','B','c','d'],'key5':['e','f','g','H'],'key6':['i','j','K','L']},index = ['p','q','u','v'])
print(df1)
#   key1 key2 key3
# k    a    e    i
# l    b    f    j
# m    c    g    k
# n    d    h    l
print(df2)
#   key4 key5 key6
# p    a    e    i
# q    B    f    j
# u    c    g    K
# v    d    H    L
df3 = pd.merge(df1,df2,left_on='key1',right_on='key4')
print(df3)
#   key1 key2 key3 key4 key5 key6
# 0    a    e    i    a    e    i
# 1    c    g    k    c    g    K
# 2    d    h    l    d    H    L

3 分组

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

在pandas中类似的分组的操作我们有很简单的方式来完成

df.groupby(by=“columns_name”)

grouped = df.groupby(by=“columns_name”)

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

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

元组里面是(索引(分组的值),分组之后的DataFrame)

对于groupby对象数据,我们还可以进行一些统计操作,比如count()、sum()、mean()等方法,在经过这些方法处理之后,会生成一个新的DataFrame()数据帧,这个数据帧每一个记录的index是刚才groupby分类依据那一列的值,而一个记录中每个字段的值则是根据统计计算出来这个分类当中的统计参数。相当于用这个数代表了这个类的特点。

file_path = "starbucks_store_worldwide.csv"

df = pd.read_csv(file_path)
print(df.head(1))
# print(df.info())
grouped = df.groupby(by="Country")
# print(grouped)

#DataFrameGroupBy
# 可以进行遍历
# for i,j in grouped:
#     print(i)
#     print("-"*100)
#     print(j,type(j))
#     print("*"*100)
# print(df[df["Country"]=="US"])
#调用聚合方法
# print(grouped.count())

#统计中、美两国星巴克的数量
country_count = grouped["Brand"].count() #对每个国家的‘Brand’列进行数据统计,因为是以国家名称进行groupby的,grouped["Brand"]的行索引仍然为国家,只是单独取出了'Brand'这一列
print(country_count)
print(type(country_count)) #<class 'pandas.core.series.Series'>
#经过mean,sum,min等统计操作后,对象变成dataframe或series
print(country_count["US"]) #使用Series索引获取值
print(country_count["CN"])

#统计中国每个省店铺的数量
china_data = df[df["Country"] =="CN"]
print(china_data)
grouped = china_data.groupby(by="State/Province").count()["Brand"]
print(grouped)

# 数据按照多个条件进行分组,返回Series
grouped = df["Brand"].groupby(by=[df["Country"],df["State/Province"]]).count()
print(grouped)
print(type(grouped)) #只有最后一列是数据,前两列是index,类型仍然为Series

#数据按照多个条件进行分组,返回DataFrame
grouped1 = df[["Brand"]].groupby(by=[df["Country"],df["State/Province"]]).count()#Brand为方括号,取多列(虽然只有一列数据,但数据类型仍然是Dataframe)
grouped2= df.groupby(by=[df["Country"],df["State/Province"]])[["Brand"]].count()
grouped3 = df.groupby(by=[df["Country"],df["State/Province"]]).count()[["Brand"]]

print(grouped1,type(grouped1))
print("*"*100)
print(grouped2,type(grouped2))
print("*"*100)
print(grouped3,type(grouped3))

#索引的方法和属性
print(grouped1.index)
# MultiIndex([('AD',  '7'),
#             ...
#             ('ZA', 'GT')],
#            names=['Country', 'State/Province'], length=545)

4 索引和复合索引

简单的索引操作:

获取index:df.index

指定index :df.index = [‘x’,‘y’]

重新设置index : df.reindex(list(“abcedf”)) #相当于从df中取了几行,原df不变

指定某一列作为index :df.set_index(“Country”,drop=False)

返回index的唯一值:df.set_index(“Country”).index.unique() #索引可以重复

import pandas as pd
a = pd.DataFrame({'a': range(7),'b': range(7, 0, -1),'c': ['one','one','one','two','two','two', 'two'],'d': list("hjklmno")})
print(a)
#    a  b    c  d
# 0  0  7  one  h
# 1  1  6  one  j
# 2  2  5  one  k
# 3  3  4  two  l
# 4  4  3  two  m
# 5  5  2  two  n
# 6  6  1  two  o
b = a.set_index(['c','d'])
print(b)
#        a  b
# c   d
# one h  0  7
#     j  1  6
#     k  2  5
# two l  3  4
#     m  4  3
#     n  5  2
#     o  6  1
print('*'*100)
print(b.loc['one']) #如果'one'在里面,使用df.swaplevel()
#    a  b
# d
# h  0  7
# j  1  6
# k  2  5
print(b.loc['one'].loc['j'])
# a    1
# b    6
c = b['a']
print(c)
# c    d
# one  h    0
#      j    1
#      k    2
# two  l    3
#      m    4
#      n    5
#      o    6
print(c['one']['j']) #1
print(c['one','h'])  #0 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值