编写本篇文章的目的:了解Python数据处理的基本步骤,计算美国各州的人口密度,数据来源:https://github.com/jakevdp/data-USstates/
,共3张数据表格:state-population.csv,state-areas.csv,state-abbrevs.csv
数据说明:
字段 | state/region | ages | year | population |
说明 | 州/区域 | 人口年龄 | 年份 | 人口数量 |
备注 | 显示为每个州的简称,与state-abbrevs.csv文件中的abbreviation对应 | 包括18岁以下,全部年龄段等 |
字段 | state | area (sq. mi) |
说明 | 区域 | 区域面积 |
备注 | 全称,与state-abbrevs.csv文件中的state字段相对应 |
字段 | state | abbreviation |
说明 | 区域(各州名称) | 各州名称简称 |
备注 | 全称,与state-areas.csv文件中state字段对应 | 与state-population.csv 文件中的state/region字段对应 |
环境:使用anaconda集成环境中的Spyder软件,打开软件,首先新建一个项目(projects),然后所有的操作都在project里面实现。创建项目适用于有大型项目中,本次只是一个小型的数据处理项目,也可以选择不创建项目。
1.读入数据
语句为:pd.read_csv('文件路径'),语句较为简单,但最重要的是要注意文件路径,以本篇为例,讲解几个注意点。
小编的文件路径为:E:\data\data-USstates-master\state-population.csv,这是电脑上直接复制的文件地址;
Python的路径格式为:E://data//data-USstates-master//state-population.csv,也就是把'\'变成了‘//’,当然为了代码的美观程度也可以写成:r'E:/data/data-USstates-master/state-population.csv'。
看起来比较繁琐,因为这是绝对路径,适用于数据文件和运行文件.py不在同一文件夹下。
很多时候我们会考虑到使用相对路径,这样我们一般把数据文件和.py文件放入一个工作目录下。比如小编的.py文件就在E:\data\data-USstates-master\USstate_data目录下,所以读取相对路径就可以写成:r'../state-population.csv',其中‘../’表示回到上层。
2.观察数据
使用的数据观察函数为df.head(),df.describe(),df.tail(),len(df)等,其中head()和tail()分别显示前10条数据和后10条数据,describe()会显示数值型数据的基本统计信息,包括总数据行(与len(df)统计结果一致)、均值、中位数、标准差、最小值、最大值以及其他统计结果。
3.数据处理
数据处理包括:数据合并、缺失值处理、异常值处理、数据插补等。具体处理方法视数据情况而定。
本篇文章涉及到了数据合并和缺失值的基本处理等。
将三个数据文件分别存储为数据框,以字段说明,发现三个数据文件中都存在两两相关的关系,然后合并这三个数据文件。
代码:pd.merge(left, right, how='inner', on=None, 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 : 数据框
how : {'left', 'right', 'outer', 'inner'}, 默认为 'inner'
* left: 只使用左表的键,类似于SQL的左外连接,保留键的顺序
* right:只使用右表的键,类似于SQL的右外连接,保留键的顺序
* outer:保留两张表的所有键, 类似于SQL的全连接
* inner: 取左右两个键不重合的部分,类似于SQL的内连接,保留左表键的顺序
on : 标签或者列表(列表中为多个标签),一般指列名
left_on :左表的连接列名、列表或者数组,适用于左右表连接列名称不同的情况下,结合right_on使用
right_on : 右表的连接列名、列表或者数组,配合left_on使用
left_index : 布尔类型, 默认为 False,适用于左右表共同属性为索引的时候
right_index : 布尔类型, 默认为 False
sort : 布尔类型,默认为 False,主要是对连接后的结果集按字母顺序排序
suffixes : 输出结果中有两个重复列名时,该参数自定义后缀名
删除重复行代码:df.drop(列名, axis=0/1)
(1)合并数据,先合并人口数量表和区域表的数据
merged = pd.merge(pop, abbrevs, how='outer', left_on='state/region', right_on='abbreviation')
merged = merged.drop('abbreviation', axis=1) #axis=1可以直接写为1,且axis为必要参数,必须指定
merged.head()
(2)缺失值观察及简单插补
用df.isnull().any()函数查看是否有缺失值及所在列,发现state和population中有缺失值,考虑到名称缩写没有匹配上的可能性,查看缺失的数据来源,使用merged.loc[merged['state'].isnull(), 'state/region'].unique(),得到数据是PR和USA全称没有录入导致的,所以对该部分的数据进行重新写入。代码如下:
merged.isnull().any() #返回类型为bool类型
merged[merged['population'].isnull()].head()
merged.loc[merged['state'].isnull(), 'state/region'].unique()
merged.loc[merged['state/region'] == 'PR', 'state'] = 'Puerto Rico'
merged.loc[merged['state/region'] == 'USA', 'state'] = 'United States'
merged.isnull().any()
然后合并州面积表的数据,添加各州的面积到目标数据表中,对目标表的数据进行缺失值的观察以及处理,代码如下:
final = pd.merge(merged, areas, on='state', how='left')
final.head()
final.isnull().any()
final['state'][final['area (sq. mi)'].isnull()].unique()
#查找面积数据为空的地区,并且只需要唯一值进行确定
#参数补充说明,df.dropna()删除缺失的数据,inpalce=True表示在修改数据,不创建新的对象
#inplace=False表示修改数据,创建并返回新的对象即结果
#subset,设置去除空值的列,里面是列名
final.dropna(inplace=True)
final.head()
(3)计算2010年所有年龄阶段各州的人口密度
使用query()进行数据的查询,set_index()函数设置索引的名称。代码如下:
data2010 = final.query("year == 2010 & ages == 'total'")
data2010.head()
data2010.set_index('state', inplace=True)
density = data2010['population'] / data2010['area (sq. mi)']
density.sort_values(ascending=False, inplace=True)
density.head()
density.tail()
本篇文章使用到的所有代码:
import pandas as pd
import numpy as np
#该文件的路径为:E:\data\data-USstates-master\state-population.csv
#Python路劲语法格式为:E://data//data-USstates-master//state-population.csv
#也可以写为:r'E:/data/data-USstates-master/state-population.csv'
#由于本文件创建了项目,所以可以替换为r'../state-population.csv'
#同理,如果数据文件和.py运行文件在同一文件夹下,可以直接读取
#在文件夹中的上一个文件夹中则用'../'表示回到上一层
pop = pd.read_csv(r'../state-population.csv')
areas = pd.read_csv(r'../state-areas.csv')
abbrevs = pd.read_csv(r'../state-abbrevs.csv')
#观察数据,复杂数据可以用到describe函数,格式pop.describe()
print(pop.head());
print(areas.head());
print(abbrevs.head())
#合并数据
merged = pd.merge(pop, abbrevs, how='outer', left_on='state/region', right_on='abbreviation')
merged = merged.drop('abbreviation', axis=1) #axis=1可以直接写为1,且axis为必要参数,必须指定
merged.head()
#检验缺失数据,即对每一列进行检验
merged.isnull().any() #返回类型为bool类型
merged[merged['population'].isnull()].head()
merged.loc[merged['state'].isnull(), 'state/region'].unique()
merged.loc[merged['state/region'] == 'PR', 'state'] = 'Puerto Rico'
merged.loc[merged['state/region'] == 'USA', 'state'] = 'United States'
merged.isnull().any()
final = pd.merge(merged, areas, on='state', how='left')
final.head()
final.isnull().any()
final['state'][final['area (sq. mi)'].isnull()].unique()
#查找面积数据为空的地区,并且只需要唯一值进行确定
#参数补充说明,df.dropna()删除缺失的数据,inpalce=True表示在修改数据,不创建新的对象
#inplace=False表示修改数据,创建并返回新的对象即结果
#subset,设置去除空值的列,里面是列名
final.dropna(inplace=True)
final.head()
data2010 = final.query("year == 2010 & ages == 'total'")
data2010.head()
data2010.set_index('state', inplace=True)
density = data2010['population'] / data2010['area (sq. mi)']
density.sort_values(ascending=False, inplace=True)
density.head()
density.tail()