pandas数据合并、分组聚合及其使用

一、pandas数据合并

1、join:默认情况下把行索引相同的数据合并在一起

join方法是基于index连接dataframe,merge方法是基于column连接,连接方法有内连接,外连接,左连接和右连接,与merge一致。

join操作按照左边原则进行,左边有几行,结果就会有几行,列为join操作双方列的总和,在左边未出现的赋值为NaN

import pandas as pd

import numpy as np

def myPd():

t1 = pd.DataFrame(np.arange(12).reshape(3, 4), index=list("abc"), columns=list("ABCD"))

print(t1)

t2 = pd.DataFrame(np.ones((2, 5)), columns=list("VWXYZ"), index=list("ab"))

print(t2)

print(t1.join(t2))

if __name__ == '__main__':

myPd()

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

pandas的merge方法是基于共同列,将两个dataframe连接起来。merge方法的主要参数:

left/right:左/右位置的dataframe。how:数据合并的方式。left:基于左dataframe列的数据合并;right:基于右dataframe列的数据合并;outer:基于列的数据外合并(取并集);inner:基于列的数据内合并(取交集);默认为'inner'。on:用来合并的列名,这个参数需要保证两个dataframe有相同的列名。left_on/right_on:左/右dataframe合并的列名,也可为索引,数组和列表。left_index/right_index:是否以index作为数据合并的列名,True表示是。sort:根据dataframe合并的keys排序,默认是。suffixes:若有相同列且该列没有作为合并的列,可通过suffixes设置该列的后缀名,一般为元组和列表类型。

merges通过设置how参数选择两个dataframe的连接方式,有内连接,外连接,左连接,右连接,下面通过例子介绍连接的含义。

二、pandas分组聚合

df.groupby(by = "属性名“)分组按照by指定的属性进行分组grouped.count()聚合grouped是分组好的数据,count是按照分组进行计数

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

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

1、Starbucks数据描述信息

2、数据分组(按国家)

import pandas as pd

import numpy as np

file_path = "E:/python/pyData/starbucks.csv"

df = pd.read_csv(file_path)

#分组

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

print(grouped)

#pandas.core.groupby.generic.DataFrameGroupBy

#可以进行遍历

for i,j in grouped:

print(i)

print("*" * 100)

print(j)

print("-" * 100)

美国(US)对应门店详细信息:

3、数据聚合(按国家-Country)

#数据聚合

country_count = grouped["Brand"].count()

print(country_count)

print("CN_number:", country_count["US"])

print("US_number:", country_count["CN"])

4、统计中国所有省份的星巴克数目

思路:先在全球分布文件中选中中国,最后在对中国的数据按照省分组

注意:此处关于中国的省份用数字代号表示

china_data = df[df["Country"] == "CN"]

china_grouped = china_data.groupby(by="State/Province").count()["Brand"]

print(china_grouped)

部分数据展示:

5、数据按照多个条件进行分组

(1)如果我们需要对国家和省份进行分组统计,具体操作:

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

(2)获取分组之后的某一部分数据

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

(3)对某几列数据进行分组

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

注:输出中,grouped是一个Series类型

以上返回是Series类型,若想让返回值是DataFrame类型做法:

法1:grouped = df[["Brand"]].groupby(by=[df["Country"], df["State/Province"]]).count()

法2:grouped2 = df.groupby(by=[df["Country"], df["State/Province"]])[["Brand"]].count()

法3:grouped3 = df.groupby(by=[df["Country"], df["State/Province"]]).count()[["Brand"]]

三、索引和复合索引

1、简单的索引操作

获取index:df.index指定index:df.index = ["x", “y”]重新设置index:df.reindex(list("abcd"))指定某一列作为索引(index):df.set_index("COUNTRY", drop = false)返回index的唯一值,df.set_index("COUNTRY").index_unique()

注:drop参数的作用:在设定某列为索引时,是否删除对应的列

reindex重新指定索引与index直接指定新索引的区别:

reindex指定新索引,其实是在原索引中取出对应存在的行作为新的行,原索引中未出现的,对应列的数据均赋值为NaN

import pandas as pd

import numpy as np

def myPd():

df = pd.DataFrame(np.arange(12).reshape(3, 4), index=list("ABC"), columns=list("abcd"))

print(df)

print(df.index)

df.index = ["x", "y", "z"]

print(df)

print(df.index)

df = df.reindex(list("wxy"))

print(df)

print(df.index)

#设置符合索引

df = df.set_index(["a", "b"], drop=False)

print(df)

if __name__ == '__main__':

myPd()

2、重排分级排序

有时需要重新调整某条轴上各级别的顺序,或根据指定级别上的值对数据进行排序。swaplevel接受两个级别编号或名称,并返回一个互换了级别的新对象(但数据不会发生变化):

import pandas as pd

import numpy as np

def myPd():

df = pd.DataFrame(np.arange(12).reshape(3, 4), index=list("ABC"), columns=list("abcd"))

df = df.set_index(["a", "b"], drop=False)

print(df)

df = df.swaplevel()

print(df)

if __name__ == '__main__':

myPd()

四、分组聚合练习

1、使用matplotlib呈现出店铺综述排名前十的国家

2、使用matplotlib呈现出中国每个城市的店铺数量

1、需求1

import numpy as np

import pandas as pd

from matplotlib import pyplot as plt

def myDeal():

file_path = "E:/python/pyData/starbucks.csv"

df = pd.read_csv(file_path)

#数据准备,降序并取出前十

data1 = df.groupby(by="Country").count()["Brand"].sort_values(ascending=False)[:10]

_x = data1.index

_y = data1.values

#画图

plt.figure(figsize=(20, 8), dpi=80)

plt.bar(range(len(_x)), _y)

plt.xticks(range(len(_x)), _x)

plt.show()

if __name__ == '__main__':

myDeal()

2、需求2

import numpy as np

import pandas as pd

from matplotlib import pyplot as plt

from matplotlib import font_manager

def myDeal():

my_font = font_manager.FontProperties(fname="C:/Windows/Fonts/HGSS1_CNKI.TTF")

file_path = "E:/python/pyData/starbucks.csv"

df = pd.read_csv(file_path)

df = df[df["Country"] == "CN"]

#数据准备

data1 = df.groupby(by="City").count()["Brand"].sort_values(ascending=False)[:15]

_x = data1.index

_y = data1.values

#画图

plt.figure(figsize=(20, 8), dpi=80)

plt.bar(range(len(_x)), _y, width=0.3, color="orange")

plt.xticks(range(len(_x)), _x, fontproperties=my_font)

plt.show()

if __name__ == '__main__':

myDeal()

五、书籍统计练习

现在我们有全球排名靠前的10000本书的数据,那么请统计一下下面几个问题:

不同年份书籍的数量不同年份书的平均评分情况

数据来源:https://www.kaggle.com/zygmunt/goodbooks-10k

1、数据文件描述信息

2、不同年份书的平均评分情况

import numpy as np

import pandas as pd

from matplotlib import pyplot as plt

def myPd():

file_path = "E:/python/pyData/books.csv"

df = pd.read_csv(file_path)

# print(df.info())

#处理original_publication_year列的缺失值,删除,取出不为NaN的值

data1 = df[pd.notna(df["original_publication_year"])]

#求不同年份的平均值(折线图)

grouped = data1["average_rating"].groupby(by=data1["original_publication_year"]).mean()

print(grouped)

#绘图

_x = grouped.index

_y = grouped.values

plt.figure(figsize=(20, 8), dpi=80)

plt.plot(range(len(_x)), _y)

plt.xticks(list(range(len(_x)))[::10], _x, rotation=45)

plt.show()

if __name__ == '__main__':

myPd()

六、紧急救援电话案例

现在我们有2015到2017年的25万条911的紧急电话的数据,请统计出这些数据中不同类型的紧急情况的次数

数据来源:https://www.kaggle.com/mchirico/montcoalert/data

import pandas as pd

import numpy as np

def myPD():

file_path = "E:/python/pyData/911.csv"

df = pd.read_csv(file_path)

print(df.head(1))

print(df.info())

#获取分类

temp_list = df["title"].str.split(": ").tolist()

cate_list = list(set([i[0] for i in temp_list]))

#构造全为0的数组

zeros_df = pd.DataFrame(np.zeros((df.shape[0], len(cate_list))), columns=cate_list)

#赋值,按列赋值处理速度快

for cate in cate_list:

zeros_df[cate][df["title"].str.contains(cate)] = 1

sum_ret = zeros_df.sum(axis=0)

print(sum_ret)

if __name__ == '__main__':

myPD()