- pandas常用统计方法
- 数据合并之join、merge
- 分组和聚合
pandas基础内容可跳转之前文章
Pandas入门详细教程(一) pandas常用统计方法
对于这一组电影数据,如果我们希望统计电影分类(genre)的情况,应该如何处理数据?
思路:重新构造一个全为0的数组,列名为分类,如果某一条数据中分类出现过,就让0变为1
# coding=utf-8
import pandas as pd
from matplotlib import pyplot as plt
import numpy as np
file_path = "./IMDB-Movie-Data.csv"
df = pd.read_csv(file_path)
print(df["Genre"].head(3))
# 统计分类的列表 tolist数组转换为列表
temp_list = df["Genre"].str.split(",").tolist()
# 使用set 启到去重的目的
genre_list = list(set([i for j in temp_list for i in j]))
# 构造全为0的数组 columns是每个分类
zeros_df = pd.Dataframe(np.zeros((df.shape[0],len(genre_list))),columns=genre_list)
#print(zeros_df)
# 给每个电影出现分类的位置赋值1
for i in range(df.shape[0]):
zeros_df.loc[i,temp_list[i]] = 1
# print(zeros_df.head(3))
# 统计每个分类的电影的数量和
genre_count = zeros_df.sum(axis = 0)
print(genre_count)
# 排序
genre_count = genre_count.sort_values()
_x = genre_count.index
_y = genre_count.values
# 画图
plt.figure(figsize = (20, 8), dpi = 80)
plt.bar(range(len(_x)), _y, width = 0.4, color = "orange")
plt.xticks(range(len(_x)) ,_x)
plt.show()
打印结果为:
0 Action,Adventure,Sci-Fi 1 Adventure,Mystery,Sci-Fi 2 Horror,Thriller Name: Genre, dtype: object Family 51.0 Sci-Fi 120.0 Mystery 106.0 Biography 81.0 Fantasy 101.0 Horror 119.0 Action 303.0 Crime 150.0 Western 7.0 Musical 5.0 Drama 513.0 Romance 141.0 History 29.0 War 13.0 Adventure 259.0 Animation 49.0 Music 16.0 Thriller 195.0 Sport 18.0 Comedy 279.0 dtype: float64数据合并之join、merge
join:默认情况下是把行索引相同的数据合并到一起
merge:按照指定的列把数据按照一定的方式合并到一起
举例:现在我们有一组关于全球星巴克店铺的统计数据,如果我想知道美国的星巴克数量和中国的哪个多,或者我想知道中国每个省份星巴克的数量的情况,那么应该怎么办?
# coding=utf-8
import pandas as pd
import numpy as np
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)
# df[df["Country"]=="US"]
#调用聚合方法
# country_count = grouped["Brand"].count()
# print(country_count["US"])
# print(country_count["CN"])
#统计中国每个省店铺的数量
# china_data = df[df["Country"] =="CN"]
#
# 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))
#数据按照多个条件进行分组,返回Dataframe
grouped1 = df[["Brand"]].groupby(by=[df["Country"],df["State/Province"]]).count()
# 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)
分组和聚合
在pandas中类似的分组的操作我们有很简单的方式来完成
df.groupby(by="columns_name")
调用groupby方法之后返回的是什么内容?
grouped = df.groupby(by="columns_name") # grouped是一个DataframeGroupBy对象,是可迭代的 # grouped中的每一个元素是一个元组 # 元组里面是(索引(分组的值),分组之后的Dataframe)
要统计美国和中国的星巴克的数量,我们应该怎么做?
DataframeGroupBy对象有很多经过优化的方法
如果我们需要对国家和省份进行分组统计,应该怎么操作呢?
grouped = df.groupby(by=[df["Country"],df["State/Province"]])
很多时候我们只希望对获取分组之后的某一部分数据,或者说我们只希望对某几列数据进行分组,这个时候我们应该怎么办呢?
- 获取分组之后的某一部分数据:
df.groupby(by=["Country","State/Province"])["Country"].count()
- 对某几列数据进行分组:
df["Country"].groupby(by=[df["Country"],df["State/Province"]]).count()
观察结果,由于只选择了一列数据,所以结果是一个Series类型
- 如果我想返回一个Dataframe类型呢?
t1 = df[["Country"]].groupby(by=[df["Country"],df["State/Province"]]).count() t2 = df.groupby(by=["Country","State/Province"])[["Country"]].count()
以上的两条命令结果一样,和之前的结果的区别在于当前返回的是一个Dataframe类型
- 那么问题来了:和之前使用一个分组条件相比,当前的返回结果的前两列是什么?
简单的索引操作:
-
获取index:
df.index
-
指定index :
df.index = ['x','y']
-
重新设置index :
df.reindex(list("abcedf")) -
指定某一列作为index :
df.set_index("Country",drop=False) -
返回index的唯一值:
df.set_index("Country").index.unique()
假设a为一个Dataframe,那么当a.set_index([“c”,“d”])即设置两个索引的时候是什么样子的结果呢?
a = pd.Dataframe({'a': range(7),'b': range(7, 0, -1),'c': ['one','one','one','two','two','two', 'two'],'d': list("hjklmno")})
- 那么问题来了:我只想取索引h对应值怎么办?
- 那么:Dataframe是怎样取值呢?
那么,回到星巴克数据的问题上来,如果我们想单独的获取分组之后北京的星巴克总数,应该怎么做?
1.使用matplotlib呈现出店铺总数排名前10的国家
# coding=utf-8 import pandas as pd from matplotlib import pyplot as plt file_path = "./starbucks_store_worldwide.csv" df = pd.read_csv(file_path) #使用matplotlib呈现出店铺总数排名前10的国家 #准备数据 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()
2.使用matplotlib呈现出每个中国每个城市的店铺数量、
# coding=utf-8 import pandas as pd from matplotlib import pyplot as plt from matplotlib import font_manager my_font = font_manager.FontProperties(fname="/Library/Fonts/Songti.ttc") file_path = "./starbucks_store_worldwide.csv" df = pd.read_csv(file_path) df = df[df["Country"]=="CN"] #使用matplotlib呈现出店铺总数排名前10的国家 #准备数据 data1 = df.groupby(by="City").count()["Brand"].sort_values(ascending=False)[:25] _x = data1.index _y = data1.values #画图 plt.figure(figsize=(20,12),dpi=80) # plt.bar(range(len(_x)),_y,width=0.3,color="orange") plt.barh(range(len(_x)),_y,height=0.3,color="orange") plt.yticks(range(len(_x)),_x,fontproperties=my_font) plt.show()
现在我们有全球排名靠前的10000本书的数据,那么请统计一下下面几个问题:
-
不同年份书的数量
-
不同年份书的平均评分情况
# coding=utf-8 import pandas as pd from matplotlib import pyplot as plt file_path = "./books.csv" df = pd.read_csv(file_path) # print(df.head(2)) # # print(df.info()) # data1 = df[pd.notnull(df["original_publication_year"])] # # grouped = data1.groupby(by="original_publication_year").count()["title"] #不同年份书的平均评分情况 #去除original_publication_year列中nan的行 data1 = df[pd.notnull(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) print(len(_x)) plt.xticks(list(range(len(_x)))[::10],_x[::10].astype(int),rotation=45) plt.show()



