第3章 数据整理
3.0 简介
数据整理(data wranging)是数据预处理中的一个重要步骤。在“整理”数据时,最常用的数据结构是数据帧(data frame)。数据帧是呈表格状的。数据帧是用行和列来表示数据的。
由于书上写的网址我无法访问,自己下载了一个titanic.csv。
百度网盘
链接:https://pan.baidu.com/s/1cA2pieSfAxYoRIanTeaOFw
提取码:8e4d
#加载库
import pandas as pd
#将数据作为数据帧加载进来
dataframe = pd.read_csv("F://data//titanic//train.csv")
#查看前五行的数据
dataframe.head(5)
上述数据每一行代表一个人的记录
3.1 创建一个数据帧
在pandas中有很多方法可以创建一个新的数据帧对象。一个简单的办法是,使用Dataframe创建一个空数据帧并分别定义好每一列
#加载库
import pandas as pd
#创建数据帧
dataframe = pd.DataFrame()
#增加列
dataframe['Name']=['Jacky Jackson','Steven Stevenson']
dataframe['Age']=[38,25]
dataframe['Driver']=[True,False]
#查看数据帧
dataframe
创建过数据帧对象后,往其底部添加新的数据行
#创建一行
new_person = pd.Series(['Molly Mooney',40,True],index=['Name','Age','Driver'])
#追加一行
dataframe.append(new_person,ignore_index=True)
虽然pandas提供很多种方法进行创建数据帧,但是在现实生活种创建新的数据帧几乎是不存在的,一般是使用现有的数据集
3.2 描述数据
查看数据帧的一些属性
在加载完数据后,我们可以做的最简单的事情就是使用head查看前几行
import pandas as pd
#加载数据
dataframe = pd.read_csv("F://data//titanic//train.csv")
#查看数据的前两行
dataframe.head(2)
#查看维数( 891行 12列 的数据)
dataframe.shape
#使用describe来获取任何数值型列的描述性统计量(包括总和,平均值,标准差,最小值,最大值等等)
dataframe.describe()
可以使用tail函数查看数据帧的最后几行,描述性统计量不一定能全面反映数据的情况。比如0,1的情况,0,1只代表人是否幸存,此列的标准差不能提供很直观的结论。
3.3 浏览数据帧
从一个数据帧中挑出单个数据或一部分数据
使用loc或iloc能选择一个或多个数据,也能选择一行或多行数据
#加载库
import pandas as pd
#加载数据
dataframe = pd.read_csv("F://data//titanic//train.csv")
#选择第一行
dataframe.iloc[0]#行号从0到n-1
#可以使用冒号“:”来定义想要选择那些行。比如选择第2、3、4行
dataframe.iloc[1:4]
#获取到第四行为止的所有行
dataframe.iloc[:4]
索引
数据帧的索引不一定非是数值型。只要某一列在数据帧中每一行的值是唯一的,就可以将其设置为索引。
#将乘客名字设置为索引
dataframe=dataframe.set_index(dataframe['Name'])
#查看行
dataframe.loc['Braund, Mr. Owen Harris']
dataframe.head(3)
当数据帧的索引是一个标签时,loc比较常用。loc可以根据索引进行查询数据 iloc是根据行号来查找数据的,需要注意的是:行号一般是从0开始的 数据清洗时会经常使用iloc和loc需要熟悉他们
3.4 根据条件语句来选择行
选择泰坦尼克号上所有的女性乘客
#加载数据
dataframe = pd.read_csv("F://data//titanic//train.csv")
#展示Sex列的值是famale的前两行
dataframe[dataframe['Sex']=='female'].head(2)
筛选出所有年龄大于或等于60岁女性乘客的行数据
#过滤行,筛选出所有年龄大于或等于60岁女性乘客的行数据
dataframe[(dataframe['Sex']=='female')&(dataframe['Age']>=60)]
3.5 替换值
用pandas的replace函数,替换数据帧中的一些值
#用“Woman”替代Sex列中所有的female
import pandas as pd
dataframe =pd.read_csv("F://data//titanic//train.csv")
dataframe['Sex'].replace("female","Woman").head(2)
#同时替换多个值
dataframe['Sex'].replace(["female","male"],["Woman","Man"]).head(5)
replace接受正则表达式
dataframe.replace("oman","female",regex=True).head(2)
3.6 重命名列
使用rename函数重命名数据帧中的列
import pandas as pd
dataframe=pd.read_csv("F://data//titanic//train.csv")
dataframe.rename(columns={'Pclass':'Passenger Class'}).head(2)
rename方法可以传入一个字典作为参数。用字典可以同时改变多个列名
#重命名列,查看两行数据
dataframe.rename(columns={'Pclass':'Passenger Class','Sex':'Gender'}).head(2)
同时为多个列重命名,它实现的是旧列名为键,空字符串为值,创建一个字典
import collections
#创建字典
columns_names=collections.defaultdict(str)
#创建键
for name in dataframe.columns:
columns_names[name]
#查看字典
columns_names
3.7 计算最小值、最大值、总和、平均值与计数值
只有数值列才能计算其最小、最大、总和、平均值等等
import pandas as pa
dataframe = pd.read_csv("F://data//titanic//train.csv")
#计算描述性统计量
print('Maximum:',dataframe['Age'].max())
print('Minimum:',dataframe['Age'].min())
print('Mean:',dataframe['Age'].mean())
print('Sum:',dataframe['Age'].sum())
print('Count:',dataframe['Age'].count())
除了上述的描述性统计量外,pandas还提供了计算方差(var)、标准差(std)、峰态(kurt)、偏态(skew)、平均标准误差(sem)、众数(mode)、中位数(median)以及其他很多的描述性统计量.这些描述性统计量同样可以对数据帧进行操作
#查看计数
dataframe.count()
3.8 查看唯一值
使用unique函数,找出一列中所有的唯一值
import pandas as pd
dataframe=pd.read_csv("F://data//titanic//train.csv")
#筛选出唯一值
dataframe['Sex'].unique()
#使用value_counts,显示所有的唯一值以及他们出现的次数
dataframe['Sex'].value_counts()
#查看唯一值的个数
dataframe['Sex'].nunique()
有时候使用vakue_counts函数查看数据会出现异常值,需要对这种异常进行处理,在第五章会讲到
3.9 处理缺失值
筛选出数据帧中的缺失值(isnull和notnull都能返回布尔型的值来表示一个值是否缺失)
import pandas as pd
dataframe=pd.read_csv("F://data//titanic//train.csv")
#筛选出缺失值,查看前两行
dataframe[dataframe['Age'].isnull()].head(2)
pandas中没有NaN,想要使用NaN需要 先导入numpy库
import numpy as np
#用NaN替换一些值
df=dataframe['Sex']=dataframe['Sex'].replace('male',np.nan)
df
#设置缺失值
dataframe=pd.read_csv("F://data//titanic//train.csv",na_values=[np.nan,'NONE',-999])
dataframe
3.10 删除一列
使用drop删除一列。在dataframe 0代表行;1代表列。
import pandas as pd
dataframe=pd.read_csv("F://data//titanic//train.csv")
#删除列
dataframe.drop('Age',axis=1).head(2)
#想要删除多列,可以使用一组列名作为参数一次删除多列
dataframe.drop(['Age','Sex'],axis=1).head(2)
#如果某一列没有名字(常常会发生这种情况),可以使用dataframe.columns通过指定列下标的方式删除该列
dataframe.drop(dataframe.columns[1],axis=1).head(2)
除了drop之外还有del dataframe[‘Age’],但是del针对的是数据帧内部,会对数据帧本身进行修改,而drop函数并没有改变dataframe而是返回一个新的数据帧对象。
3.11 删除一行
import pandas as pd
dataframe = pd.read_csv("F://data//titanic//train.csv")
#使用条件语句删除多行
dataframe[dataframe['Sex']!='male'].head(2)
使用drop函数删除行数据(使用df.drop([0,1],axis=0)来删除前两行),而更实用的方式是在df[]中插入布尔条件
dataframe.drop([0,1],axis=0)
#删除一行,查看输出结果的前两行
dataframe[dataframe['Name']!='Heikkinen, Miss. Laina'].head(2)
#通过下标删除一行
dataframe[dataframe.index!=0].head(2)
3.12 删除重复行
使用drop_duplicates 删除所有列都完美匹配的行
import pandas as pd
dataframe=pd.read_csv("F://data//titanic//train.csv")
#删除重复行,查看输出结果的前两行
dataframe.drop_duplicates().head(2)
#用某些列来检查重复行(subset参数)
dataframe.drop_duplicates(subset=['Sex'])
上述结果只有两行,female,male 上述保留的两行是重复行中最先出现的两行,若想保留其他行可以通过keep参数来改变这个行为
#删除重复行
dataframe.drop_duplicates(subset=['Sex'],keep='last')
如果不想简单地将重复行删除,可以使用duplicated,会返回一个布尔序列来表示某一行是否为重复的行
dataframe.duplicated().head(2)
3.13 根据值对行分组
import pandas as pd
dataframe=pd.read_csv("F://data//titanic//train.csv")
#根据Sex列的值来对行分组,并计算每一列的平均值
dataframe.groupby('Sex').mean()
#特定的描述性统计量只对特定的数据类型才有意义。
dataframe.groupby('Survived')['Name'].count()
#上述对Survived进行分组,统计每组的乘客的个数
#先对Sex进行分组,再对Survived进行二次分组,最后根据分组情况求解Age列的平均值
dataframe.groupby(['Sex','Survived'])['Age'].mean()
3.14 按时间段对行分组
#使用resample按照时间段对行进行分组
#加载库
import pandas as pd
import numpy as np
#创建日期范围
time_index=pd.date_range('06/06/2017',periods=100000,freq='30S')
#创建数据帧
dataframe= pd.DataFrame(index=time_index)
#创建一列随机变量
dataframe['Sale_Amount']=np.random.randint(1,10,100000)
#按周对行进行分组,计算每一周的总和
dataframe.resample('W').sum()
默认情况下,resample会返回时间组的右边界的值(最后一个标签),作为这个组的标签。可以通过使用lable参数改变这个行为
dataframe.resample('M',label='left').count()
3.15 遍历一个列的数据
有两种办法:循环、列表解析式
import pandas as pd
dataframe=pd.read_csv("F://data//titanic//train.csv")
#以大写的形式打印前两行中的名字
for name in dataframe['Name'][0:2]:
print(name.upper())
#以大写的形式打印前两行的名字
[name.upper() for name in dataframe['Name'][0:2]]
3.16 对一列的所有元素应用某个函数
使用apply对一列的所有元素上应用某个函数
import pandas as pd
dataframe=pd.read_csv("F://data//titanic//train.csv")
#创建一个函数
def uppercase(x):
return x.upper()
#应用函数,查看前两行
dataframe['Name'].apply(uppercase)[0:2]
3.17 对所有分组应用一个函数
import pandas as pd
dataframe=pd.read_csv("F://data//titanic//train.csv")
#对行分组,然后在每一组上应用函数
dataframe.groupby('Sex').apply(lambda x:x.count())
3.18 连接多个数据帧
import pandas as pd
#创建数据帧
data_a={'id':['1','2','3'],'first':['Alex','Amy','Allen'],'last':['Anderson','Ackerman','Ali']}
dataframe_a=pd.DataFrame(data_a,columns=['id','first','last'])
data_b={'id':['4','5','6'],'first':['Billy','Brian','Bran'],'last':['Bonder','Black','Balwner']}
dataframe_b=pd.DataFrame(data_b,columns=['id','first','last'])
#沿着行的方向连接两个数据帧
pd.concat([dataframe_a,dataframe_b],axis=0)
#沿着列的方向连接两个数据帧
pd.concat([dataframe_a,dataframe_b],axis=1)
3.19 合并两个数据帧
一共有四种合并方式:等值连接、外连接、左连接、右连接
使用merge并用on参数指定哪些列需要合并
#加载库
import pandas as pd
df1 = pd.DataFrame({'key': ['b', 'b', 'a', 'c', 'a', 'a', 'b'],'data1': range(7)})
df2 = pd.DataFrame({'key': ['a', 'b', 'd'],'data2': range(3)})
pd.merge(df1, df2)
注意上面并没有指明使用哪一列作为连接的键。在这种情况下,merge函数使用重叠的列作为键进行连接。
#指定所用的列
pd.merge(df1, df2, on='key')
#使用不同名的键进行连接的情形
df3 = pd.DataFrame({'lkey': ['b', 'b', 'a', 'c', 'a', 'a', 'b'],'data1': range(7)})
df4 = pd.DataFrame({'rkey': ['a', 'b', 'd'],'data2': range(3)})
pd.merge(df3, df4, left_on='lkey', right_on='rkey')
观察上面的运行结果会发现,结果中不存在键值为’c’和’d’的行。这是因为,merge默认执行的是类似于SQL中的inner join操作,两个数据集中都存在的键才会在结果中出现。通过向merge函数传递不同的how参数,可以实现SQL中其他几种连接方式:left join、right join、outer join。
#等值连接(inner join)只返回指定列的值在两个数据帧都存在的行
#加载库
import pandas as pd
#创建dataframe
employee_data={'employee_id':['1','2','3','4'],'name':['Amy Jones','Allen Keys','Alice Bees','Tim Horton']}
dataframe_employees=pd.DataFrame(employee_data,columns=['employee_id','name'])
sales_data={'employee_id':['3','4','5','6'],'total_sales':[23456,2512,2345,1455]}
dataframe_sales=pa.DataFrame(sales_data,columns=['employee_id','total_sales'])
#合并数据帧
pd.merge(dataframe_employees,dataframe_sales,on='employee_id')
#外连接(outer join)通过how参数来指定 返回两个数据帧的所有行。如果某一行只在其中一个数据帧中存在,就用NaN来填充缺失的值
pd.merge(dataframe_employees,dataframe_sales,on='employee_id',how='outer')
#左连接(left join)返回左数据帧的所有行,对于右数据帧,只返回在左数据帧中能找到匹配值的行
pd.merge(dataframe_employees,dataframe_sales,on='employee_id',how='left')
#右连接(right join)返回右数据帧的所有行,对于左数据帧,只返回在右数据帧中能找到匹配值的行
pd.merge(dataframe_employees,dataframe_sales,on='employee_id',how='right')
#对多个key值上进行操作(将要连接key名的list作为参数)
left = pd.DataFrame({'key1': ['foo', 'foo', 'bar'],'key2': ['one', 'two', 'one'],'lval': [1, 2, 3]})
right = pd.DataFrame({'key1': ['foo', 'foo', 'bar', 'bar'],'key2': ['one', 'one', 'one', 'two'],'rval': [4, 5, 6, 7]})
pd.merge(left, right, on=['key1', 'key2'], how='outer')
使用index进行DataFrame合并
#传递left_index以及right_index参数,指示合并的时候应该使用index作为key值。
left1 = pd.DataFrame({'key': ['a', 'b', 'a', 'a', 'b', 'c'],'value': range(6)})
right1 = pd.DataFrame({'group_val': [3.5, 7]}, index=['a', 'b'])
pd.merge(left1,right1,left_on='key',right_index=True)
#默认的合并操作使用的连接方式是inner join,通过how参数改为其他连接方式
pd.merge(left1, right1, left_on='key', right_index=True, how='outer')
沿着横轴或纵轴串接
另一种数据合并的方式被称为串接。例如,NumPy库具有一个concatenate函数用于串接NumPy的原生数组。
import numpy as np
arr = np.arange(12).reshape((3, 4))#生成一个三行四列的矩阵
np.concatenate([arr, arr], axis=1)#axis=0代表按行进行合并,axis=1是按列进行合并
pandas库中,存在一个concat函数,用于实现类似的串接操作。和NumPy相比,pandas的串接操作更复杂也更通用。下面用一系列的例子来说明pandas的concat函数的用法。
s1 = pd.Series([0, 1], index=['a', 'b'])
s2 = pd.Series([2, 3, 4], index=['c', 'd', 'e'])
s3 = pd.Series([5, 6], index=['f', 'g'])
pd.concat([s1, s2, s3])#默认情况下,concat函数的axis参数取值为0,表示行的串接
#如果传递axis=1,表示列的串接,结果得到一个新的DataFrame对象。得到的结果相当于SQL的outer join
pd.concat([s1, s2, s3], axis=1)
#对s1和s4分别进行outer join和inner join
pd.concat([s1, s4], axis=1, join='inner')#返回两个数据帧均包含的数据
#concat函数也可以应用在DataFrame对象上
import numpy as np
df1 = pd.DataFrame(np.arange(6).reshape(3, 2), index=['a', 'b', 'c'],columns=['one', 'two'])
df2 = pd.DataFrame(5 + np.arange(4).reshape(2, 2), index=['a', 'c'],columns=['three', 'four'])
pd.concat([df1,df2],axis=1)
第3章 完工啦!!!