跳转至

4 Pandas 数据分析入门

学习目标

  • 掌握在Pandas中计算常用统计量的方法
  • 熟练使用pandas进行简单排序、分组、聚合等计算

1 计算常用统计值

  • 加载数据之后,可以通过计算最大值,最小值,平均值,分位数,方差等方式对数据的分布情况做基本了解
college = pd.read_csv('data/college.csv')
college.head()

输出结果

INSTNM CITY STABBR HBCU MENONLY WOMENONLY RELAFFIL SATVRMID SATMTMID DISTANCEONLY ... UGDS_2MOR UGDS_NRA UGDS_UNKN PPTUG_EF CURROPER PCTPELL PCTFLOAN UG25ABV MD_EARN_WNE_P10 GRAD_DEBT_MDN_SUPP
0 Alabama A & M University Normal AL 1.0 0.0 0.0 0 424.0 420.0 0.0 ... 0.0000 0.0059 0.0138 0.0656 1 0.7356 0.8284 0.1049 30300 33888
1 University of Alabama at Birmingham Birmingham AL 0.0 0.0 0.0 0 570.0 565.0 0.0 ... 0.0368 0.0179 0.0100 0.2607 1 0.3460 0.5214 0.2422 39700 21941.5
2 Amridge University Montgomery AL 0.0 0.0 0.0 1 NaN NaN 1.0 ... 0.0000 0.0000 0.2715 0.4536 1 0.6801 0.7795 0.8540 40100 23370
3 University of Alabama in Huntsville Huntsville AL 0.0 0.0 0.0 0 595.0 590.0 0.0 ... 0.0172 0.0332 0.0350 0.2146 1 0.3072 0.4596 0.2640 45500 24097
4 Alabama State University Montgomery AL 1.0 0.0 0.0 0 425.0 430.0 0.0 ... 0.0098 0.0243 0.0137 0.0892 1 0.7347 0.7554 0.1270 26600 33118.5

5 rows × 27 columns

  • 数据字段
college.columns

输出结果

Index(['INSTNM', 'CITY', 'STABBR', 'HBCU', 'MENONLY', 'WOMENONLY', 'RELAFFIL',
      'SATVRMID', 'SATMTMID', 'DISTANCEONLY', 'UGDS', 'UGDS_WHITE',
      'UGDS_BLACK', 'UGDS_HISP', 'UGDS_ASIAN', 'UGDS_AIAN', 'UGDS_NHPI',
      'UGDS_2MOR', 'UGDS_NRA', 'UGDS_UNKN', 'PPTUG_EF', 'CURROPER', 'PCTPELL',
      'PCTFLOAN', 'UG25ABV', 'MD_EARN_WNE_P10', 'GRAD_DEBT_MDN_SUPP'],
     dtype='object')
  • 查看数据行列数
college.shape

输出结果

(7535, 27)
  • 统计数值列,并进行转置
college.describe().T

输出结果

count mean std min 25% 50% 75% max
HBCU 7164.0 0.014238 0.118478 0.0 0.000000 0.00000 0.000000 1.0000
MENONLY 7164.0 0.009213 0.095546 0.0 0.000000 0.00000 0.000000 1.0000
WOMENONLY 7164.0 0.005304 0.072642 0.0 0.000000 0.00000 0.000000 1.0000
RELAFFIL 7535.0 0.190975 0.393096 0.0 0.000000 0.00000 0.000000 1.0000
SATVRMID 1185.0 522.819409 68.578862 290.0 475.000000 510.00000 555.000000 765.0000
SATMTMID 1196.0 530.765050 73.469767 310.0 482.000000 520.00000 565.000000 785.0000
DISTANCEONLY 7164.0 0.005583 0.074519 0.0 0.000000 0.00000 0.000000 1.0000
UGDS 6874.0 2356.837940 5474.275871 0.0 117.000000 412.50000 1929.500000 151558.0000
UGDS_WHITE 6874.0 0.510207 0.286958 0.0 0.267500 0.55570 0.747875 1.0000
UGDS_BLACK 6874.0 0.189997 0.224587 0.0 0.036125 0.10005 0.257700 1.0000
UGDS_HISP 6874.0 0.161635 0.221854 0.0 0.027600 0.07140 0.198875 1.0000
UGDS_ASIAN 6874.0 0.033544 0.073777 0.0 0.002500 0.01290 0.032700 0.9727
UGDS_AIAN 6874.0 0.013813 0.070196 0.0 0.000000 0.00260 0.007300 1.0000
UGDS_NHPI 6874.0 0.004569 0.033125 0.0 0.000000 0.00000 0.002500 0.9983
UGDS_2MOR 6874.0 0.023950 0.031288 0.0 0.000000 0.01750 0.033900 0.5333
UGDS_NRA 6874.0 0.016086 0.050172 0.0 0.000000 0.00000 0.011700 0.9286
UGDS_UNKN 6874.0 0.045181 0.093440 0.0 0.000000 0.01430 0.045400 0.9027
PPTUG_EF 6853.0 0.226639 0.246470 0.0 0.000000 0.15040 0.376900 1.0000
CURROPER 7535.0 0.923291 0.266146 0.0 1.000000 1.00000 1.000000 1.0000
PCTPELL 6849.0 0.530643 0.225544 0.0 0.357800 0.52150 0.712900 1.0000
PCTFLOAN 6849.0 0.522211 0.283616 0.0 0.332900 0.58330 0.745000 1.0000
UG25ABV 6718.0 0.410021 0.228939 0.0 0.241500 0.40075 0.572275 1.0000
  • 统计对象和类型列
    • pandas 基于 numpy,numpy支持的数据类型,pandas都支持
    • np.object 字符串类型
import numpy as np

college.describe(include='all') # 统计所有的列 包括数值列和类别类型 字符串类型
college.describe(include=object) # 类别类型 字符串类型

输出结果

count unique top freq
INSTNM 7535 7535 Institute of American Indian and Alaska Native... 1
CITY 7535 2514 New York 87
STABBR 7535 59 CA 773
MD_EARN_WNE_P10 6413 598 PrivacySuppressed 822
GRAD_DEBT_MDN_SUPP 7503 2038 PrivacySuppressed 1510
  • 通过info 方法了解不同字段的条目数量,数据类型,是否缺失及内存占用情况
college.info()

输出结果

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 7535 entries, 0 to 7534
Data columns (total 27 columns):
INSTNM                7535 non-null object
CITY                  7535 non-null object
STABBR                7535 non-null object
HBCU                  7164 non-null float64
MENONLY               7164 non-null float64
WOMENONLY             7164 non-null float64
RELAFFIL              7535 non-null int64
SATVRMID              1185 non-null float64
SATMTMID              1196 non-null float64
DISTANCEONLY          7164 non-null float64
UGDS                  6874 non-null float64
UGDS_WHITE            6874 non-null float64
UGDS_BLACK            6874 non-null float64
UGDS_HISP             6874 non-null float64
UGDS_ASIAN            6874 non-null float64
UGDS_AIAN             6874 non-null float64
UGDS_NHPI             6874 non-null float64
UGDS_2MOR             6874 non-null float64
UGDS_NRA              6874 non-null float64
UGDS_UNKN             6874 non-null float64
PPTUG_EF              6853 non-null float64
CURROPER              7535 non-null int64
PCTPELL               6849 non-null float64
PCTFLOAN              6849 non-null float64
UG25ABV               6718 non-null float64
MD_EARN_WNE_P10       6413 non-null object
GRAD_DEBT_MDN_SUPP    7503 non-null object
dtypes: float64(20), int64(2), object(5)
memory usage: 1.6+ MB

2 常用排序方法

2.1 从最大的N个值中选取最小值——找到小成本高口碑电影

movie = pd.read_csv('data/movie.csv')
movie2 = movie[['movie_title', 'imdb_score', 'budget']]
movie2.head()

输出结果

movie_title imdb_score budget
0 Avatar 7.9 237000000.0
1 Pirates of the Caribbean: At World's End 7.1 300000000.0
2 Spectre 6.8 245000000.0
3 The Dark Knight Rises 8.5 250000000.0
4 Star Wars: Episode VII - The Force Awakens 7.1 NaN
  • 用nlargest方法,选出imdb_score分数最高的100个
movie2.nlargest(100, 'imdb_score').head()

输出结果

movie_title imdb_score budget
2725 Towering Inferno 9.5 NaN
1920 The Shawshank Redemption 9.3 25000000.0
3402 The Godfather 9.2 6000000.0
2779 Dekalog 9.1 NaN
4312 Kickboxer: Vengeance 9.1 17000000.0
  • 使用nsmallest方法再从中挑出预算最小的五部
movie2.nlargest(100, 'imdb_score').nsmallest(5, 'budget')

输出结果

movie_title imdb_score budget
4804 Butterfly Girl 8.7 180000.0
4801 Children of Heaven 8.5 180000.0
4706 12 Angry Men 8.9 350000.0
4550 A Separation 8.4 500000.0
4636 The Other Dream Team 8.4 500000.0

2.2 通过排序选取每组的最大值——找到每年imdb评分最高的电影

  • sort_values 按照年排序,ascending 升序排列
movie2 = movie[['movie_title', 'title_year', 'imdb_score']]
movie2.sort_values('title_year', ascending=False).head()

输出结果

movie_title title_year imdb_score
3884 The Veil 2016.0 4.7
2375 My Big Fat Greek Wedding 2 2016.0 6.1
2794 Miracles from Heaven 2016.0 6.8
92 Independence Day: Resurgence 2016.0 5.5
153 Kung Fu Panda 3 2016.0 7.2
  • 同时对'title_year','imdb_score' 两列进行排序
movie3 = movie2.sort_values(['title_year','imdb_score'], ascending=False)
movie3.head()

输出结果

movie_title title_year imdb_score
4312 Kickboxer: Vengeance 2016.0 9.1
4277 A Beginner's Guide to Snuff 2016.0 8.7
3798 Airlift 2016.0 8.5
27 Captain America: Civil War 2016.0 8.2
98 Godzilla Resurgence 2016.0 8.2
  • 用drop_duplicates去重,只保留每年的第一条数据
movie_top_year = movie3.drop_duplicates(subset='title_year')
movie_top_year.head()

输出结果

movie_title title_year imdb_score
4312 Kickboxer: Vengeance 2016.0 9.1
3745 Running Forever 2015.0 8.6
4369 Queen of the Mountains 2014.0 8.7
3935 Batman: The Dark Knight Returns, Part 2 2013.0 8.4
3 The Dark Knight Rises 2012.0 8.5

2.3 提取出每年,每种电影分级中预算少的电影——sort_values多列排序

  • 多列排序时,ascending 参数传入一个列表,排序一一对应
movie4 = movie[['movie_title', 'title_year', 'content_rating', 'budget']]
# 多列排序,ascending=[False, False, True] 降序,降序,升序
movie4_sorted = movie4.sort_values(['title_year', 'content_rating', 'budget'], ascending=[False, False, True])
# 去重,删除'title_year', 'content_rating'相同的数据
movie4_sorted.drop_duplicates(subset=['title_year', 'content_rating']).head(10)

输出结果

movie_title title_year content_rating budget
4026 Compadres 2016.0 R 3000000.0
4658 Fight to the Finish 2016.0 PG-13 150000.0
4661 Rodeo Girl 2016.0 PG 500000.0
3252 The Wailing 2016.0 Not Rated NaN
4659 Alleluia! The Devil's Carnival 2016.0 NaN 500000.0
4731 Bizarre 2015.0 Unrated 500000.0
812 The Ridiculous 6 2015.0 TV-14 NaN
4831 The Gallows 2015.0 R 100000.0
4825 Romantic Schemer 2015.0 PG-13 125000.0
3796 R.L. Stine's Monsterville: The Cabinet of Souls 2015.0 PG 4400000.0

3 简单数据分析练习(租房数据)

  • 载入数据
import pandas as pd
house_data = pd.read_csv('data/LJdata.csv')
  • 把列名替换成英文
#查看原始列名
house_data.columns

输出结果

Index(['区域', '地址', '标题', '户型', '面积', '价格', '楼层', '建造时间', '朝向', '更新时间', '看房人数','备注', '链接地址'],dtype='object')
house_data.columns = ['district', 'address', 'title', 'house_type', 'area', 'price', 'floor', 'build_time', 'direction', 'update_time', 'view_num', 'extra_info', 'link']
  • 查看数据基本情况
house_data.head()

输出结果

district address title house_type area price floor build_time direction update_time view_num extra_info link
0 燕莎租房 新源街 亮马桥 新源街 精装两居 交通便利 看房方便 随时入住 2室1厅 50平米 5800 中楼层(共6层) 1981年建板楼 2017.07.21 26 随时看房 精装修 集中供暖 https://bj.lianjia.com/zufang/101101803342.html
1 望京租房 澳洲康都 澳洲康都东向精致两居室........... 2室1厅 79平米 7800 中楼层(共28层) 2005年建板塔结合 2017.07.23 33 距离14号线(东段)东湖渠站731米 随时看房 精装修 集中供暖 https://bj.lianjia.com/zufang/101101753126.html
2 广安门租房 远见名苑 远见名苑 东向两居室 独立小区环境 适合居家 2室1厅 86平米 8000 低楼层(共25层) 2006年建塔楼 2017.07.20 34 距离7号线达官营站684米 随时看房 精装修 自供暖 https://bj.lianjia.com/zufang/101101756753.html
3 天通苑租房 天通苑北一区 北一区简装两居,采光好,视野美,出行方便 2室1厅 103平米 5300 低楼层(共13层) 2004年建板楼 东南 2017.07.25 30 距离5号线天通苑站927米 随时看房 精装修 集中供暖 https://bj.lianjia.com/zufang/101101780034.html
4 团结湖租房 团结湖北口 团结湖北口近地铁高楼层朝南向精装修正规两居室 2室1厅 63平米 6400 高楼层(共16层) 1982年建塔楼 2017.07.26 30 距离10号线团结湖站88米 随时看房 精装修 集中供暖 https://bj.lianjia.com/zufang/101101781083.html
house_data.info()

输出结果

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 2760 entries, 0 to 2759
Data columns (total 13 columns):
district       2760 non-null object
address        2760 non-null object
title          2760 non-null object
house_type     2760 non-null object
area           2760 non-null object
price          2760 non-null int64
floor          2760 non-null object
build_time     2758 non-null object
direction      2760 non-null object
update_time    2760 non-null object
view_num       2760 non-null int64
extra_info     2760 non-null object
link           2760 non-null object
dtypes: int64(2), object(11)
memory usage: 280.4+ KB
house_data.shape

输出结果

(2760, 13)
house_data.describe()

输出结果

price view_num
count 2760.000000 2760.000000
mean 7570.800725 13.448913
std 6316.204986 12.746202
min 1300.000000 0.000000
25% 4500.000000 4.000000
50% 6000.000000 10.000000
75% 8500.000000 19.000000
max 210000.000000 122.000000
  • 找到租金最低,和租金最高的房子
house_data.loc[house_data['price']==210000]
house_data.loc[house_data['price']==1300]
house_data[house_data['price']==house_data['price'].min()]
house_data[house_data['price']==house_data['price'].max()]
  • sort_values按照值排序 参数by 传入列名 参数 ascending(升序)
house_data.sort_values(by='price').head(1)

输出结果

district address title house_type area price floor build_time direction update_time view_num extra_info link
2527 良乡租房 伟业嘉园西里 半地下室 家电齐全 集中供暖 简单装修 1室1厅 46平米 1300 地下室(共5层) 2005年建 2017.07.19 14 随时看房 集中供暖
house_data.sort_values(by='price').tail(1)

输出结果

district address title house_type area price floor build_time direction update_time view_num extra_info link
2658 和平里租房 雍和家园二期 雍和家园 底商出租 使用面积720米 6室3厅 720平米 210000 低楼层(共6层) 2005年建板楼 2017.07.26 21 距离2号线雍和宫站293米 随时看房 集中供暖
  • 找到最近新上的10套房源
house_data.sort_values(by='update_time', ascending=False).head(10)

输出结果

district address title house_type area price floor build_time direction update_time view_num extra_info link
347 劲松租房 武圣西里 武圣西里正规三居室,低楼层,看房方便 3室1厅 73平米 6500 低楼层(共6层) 1986年建板楼 东南 北 2017.07.27 0 距离10号线潘家园站965米 随时看房 https://bj.lianjia.com/zufang/101101862495.html
1790 广安门租房 恒昌花园 广安门恒昌花园西向三居室集中供暖 3室2厅 159平米 13500 高楼层(共28层) 1999年建塔楼 西 2017.07.27 12 距离7号线达官营站292米 随时看房 集中供暖 https://bj.lianjia.com/zufang/101101692254.html
2405 武夷花园租房 月亮城堡 月亮城堡精装修正规一居 南北通透 户型好 1室1厅 102平米 4500 低楼层(共11层) 2005年建板塔结合 南 北 2017.07.27 28 随时看房 精装修 集中供暖 https://bj.lianjia.com/zufang/101101495373.html
2639 常营租房 北京像素南区 北京像素 地铁6号线草房 北向开间 1房间1卫 48平米 3750 低楼层(共23层) 2012年建板塔结合 2017.07.27 3 距离6号线草房站66米 随时看房 精装修 集中供暖 https://bj.lianjia.com/zufang/101101852394.html
2366 马甸租房 北太平庄路 牡丹园精装一居室 可当两居 350米到10号线 南北通透 1室1厅 33平米 4000 低楼层(共5层) 1985年建板楼 2017.07.27 24 距离10号线牡丹园站335米 随时看房 精装修 集中供暖 https://bj.lianjia.com/zufang/101101622752.html
  • 查看所有更新时间
#查看所有更新时间
house_data['update_time'].unique()

输出结果

array(['2017.07.21', '2017.07.23', '2017.07.20', '2017.07.25',
      '2017.07.26', '2017.07.16', '2017.07.22', '2017.07.24',
      '2017.07.27', '2017.07.19', '2017.07.14', '2017.07.15',
      '2017.07.17', '2017.07.18'], dtype=object)
  • 看房人数
house_data['view_num'].mean() #平均值
house_data['view_num'].median() #中位数
# 通过describe()可以查看到
  • 不同看房人数的房源数量,as_index = False 分组字段不作为行索引(默认为True)
tmp_df = house_data.groupby('view_num',as_index=False)['district'].count()
tmp_df.columns = ['view_num', 'count']
tmp_df.head()

输出结果

view_num count
0 0 152
1 1 149
2 2 143
3 3 129
4 4 147
  • 画图 %matplotlib inline 功能是在jupyter notebook中内嵌绘图,并且可以省略掉 plt.show()
%matplotlib inline
tmp_df['count'].plot(kind='bar',figsize=(20,10))

输出结果

<matplotlib.axes._subplots.AxesSubplot at 0x14e1763fc88>

img

  • 房租价格的分布
print(house_data['price'].mean())   #平均值
print(house_data['price'].std())    #标准差
print(house_data['price'].median())  #中位数

输出结果

7570.800724637681
6316.204986067457
6000.0
  • 看房人数最多的朝向
popular_direction = house_data.groupby('direction',as_index=False)[['view_num']].sum()
popular_direction[popular_direction['view_num']==popular_direction['view_num'].max()]

输出结果

direction view_num
23 南 北 11785
  • 房型分布情况
# 设置正常显示汉字和负号
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei'] # 正常显示汉字
plt.rcParams['axes.unicode_minus'] = False # 正常显示负号
house_type_dis = house_data.groupby(['house_type']).count()
%matplotlib inline
house_type_dis['district'].plot(kind='bar') #柱状图

输出结果

<matplotlib.axes._subplots.AxesSubplot at 0x14e17db17b8>

img

  • 最受欢迎的房型
tmp = house_data.groupby('house_type',as_index=False).agg({'view_num':'sum'})
tmp[tmp['view_num']==tmp['view_num'].max()]

输出结果

house_type view_num
5 2室1厅 17589
  • 房子的平均租房价格 (元/平米)
house_data.loc[:,'price_per_m2'] = house_data['price']/house_data['area']
house_data['price_per_m2'].mean()

输出结果

87.72268429900454
  • 热门小区
address_df = house_data[['address','view_num']].groupby(['address'],as_index=False).sum()
address_df.sort_values(by='view_num', ascending=False).head()

输出结果

address view_num
951 清芷园 246
369 卡布其诺 245
938 润枫水尚 217
1149 芍药居北里 194
743 新康园 186
  • 出租房源最多的小区
tmp_df2 = house_data[['address','view_num']].groupby(['address'],as_index=False).count()
tmp_df2.columns =  ['address','count']
tmp_df2.nlargest(columns='count', n=1)

输出结果

address count
1288 远洋山水 19

小结

  • 掌握在Pandas中计算常用统计量的方法
  • info 了解不同字段的条目数量,数据类型,是否缺失及内存占用情况
  • describe 计算数值类型数据的常用统计量
  • 熟练使用pandas进行简单排序、分组、聚合等计算
  • nlargest 返回指定字段的前n个最大值
  • nsmallest 返回指定字段的前n个最小值
  • sort_values 指定字段,按值排序
  • groupby 按字段分组
  • agg 分组之后聚合