数据框(Dataframe)作为一种十分标准的数据结构,是数据分析中最常用的数据结构,在Python和R中各有对数据框的不同定义和操作。
Python
本文涉及Python数据框,为了更好的视觉效果,使用jupyter notebook作为演示的编辑器;Python中的数据框相关功能集成在数据分析相关包pandas中,下面对一些常用的关于数据框的知识进行说明:
1.数据框的创建
import pandas as pd from numpy import random a = [i for i in range(10)] b = [random.randint(1,10) for i in range(10)] c = ['a','b','c','d','e','f','g','h','i','j'] data = pd.DataFrame({'a':a,'b':b,'c':c}) data
pd.DataFrame()中的常用参数:
data:可接受numpy中的ndarray,标准的字典,dataframe,其中,字典的值可以为Series,arrays,常数或列表
index:数据框行的索引值,默认为0,1,...,到length(数据框)
columns:数据框列的标签,可用于索引数据框,默认同index
dtype:强制数据框内数据转向的数据类型,如(float64)
copy:是否对输入的数据采取复制的方法生成数据框
2.数据框内容的索引
方式1:
直接通过列的名称调取数据框的中列
data['c'][2]
data['a']
data['c'][2:]
方式2:
loc[]:通过行标签调用数据内容
data = [[1,2,3],[4,5,6]] index = ['a','b'] columns = ['A','B','C'] mydata = pd.DataFrame(data,index=index,columns=columns) mydata.loc['a']
iloc[]:通过行列序号调取内容
data = [[1,2,3],[4,5,6]] index = ['a','b'] columns = ['A','B','C'] mydata = pd.DataFrame(data,index=index,columns=columns) mydata.iloc[1]
mydata.iloc[0:2]
mydata.iloc[0,2]
3.数据框的拼接操作
pd.concat()方法:
pd.cancat()的相关参数:
objs:要进行拼接的数据框名称构成的列表,如[dataframe1,dataframe2]
axis:按行向下拼接(0)还是按列向右拼接(1),默认0
ingore_index:axis所在方向上标签在合并后是否重置,默认False
keys:是否对拼接的几个素材数据框进行二级标号(即在每部分子数据框拼接开始处创建外层标签)
按列拼接数据框:
data = [[1,2,3],[4,5,6]] index = ['a','b'] columns = ['A','B','C'] mydata = pd.DataFrame(data,index=index,columns=columns) pd.concat([mydata,mydata],axis=1,keys=['1','2'])
按行拼接数据框且重置行标号:
data = [[1,2,3],[4,5,6]] index = ['a','b'] columns = ['A','B','C'] mydata = pd.DataFrame(data,index=index,columns=columns) pd.concat([mydata,mydata],axis=0,ignore_index=True)
df.append()方法
与列表append()不同,这里的append是用来上下拼接数据框:
data = [[1,2,3],[4,5,6]] index = ['a','b'] columns = ['A','B','C'] mydata = pd.DataFrame(data,index=index,columns=columns) mydata.append([mydata,mydata])
append()也有参数ignore_index
data = [[1,2,3],[4,5,6]] index = ['a','b'] columns = ['A','B','C'] mydata = pd.DataFrame(data,index=index,columns=columns) mydata.append([mydata,mydata],ignore_index=True)
4.数据框的合并操作
pd.merge()
参数介绍:
left:第一个数据框对象
right:第二个数据框对象
how:连接方式,包括‘left’,'right','inner','outer',默认为'inner'
on:两个数据框共同拥有的一列,作为连接键;若不传参数,且left_index与right_index都等于False,则自动识别两个数据框同名的列作为联结键
left_index:为True时,以左侧数据框的行标签作为联结键
right_index:为True时,以右侧数据框的行标签作为联结键
sort:为True时,在合并之后以联结键为排序依据进行排序
suffixes:一个元组,储存对两个数据框中重复非联结键列进行重命名的后缀,默认为('_x','_y')
indicator:是否生成一列新值_merge,来为合并后的每行标记其中的数据来源,有left_only,right_only,both三种可能
ID = ['001','002','003','004'] A = ['A1','A2','A3','A4'] B = ['B1','B2','B3','B4'] C = ['C1','C2','C3','C4'] D = ['D1','D2','D3','D4'] df1 = pd.DataFrame({'ID':ID, 'A':A, 'B':B}) df2 = pd.DataFrame({'ID':ID, 'C':C, 'D':D}) pd.merge(left=df1,right=df2,on='ID')
当联结键所在列有互异的部分时:
ID = ['001','002','003','005'] A = ['A1','A2','A3','A4'] B = ['B1','B2','B3','B4'] C = ['C1','C2','C3','C4'] D = ['D1','D2','D3','D4'] df1 = pd.DataFrame({'ID':ID, 'A':A, 'B':B}) df2 = pd.DataFrame({'ID':['001','002','003','004'], 'C':C, 'D':D}) df1
df2
how='inner'时:
pd.merge(left=df1,right=df2,on='ID',how='inner')
how='outer'时:
pd.merge(left=df1,right=df2,on='ID',how='outer')
可以看出,当how=’inner‘时,得到的合并数据框会自动剔除存在数据缺失的行,只保留完美的行,'outer'时则相反
dataframe.join()
join()的一些常用参数:
other:join()的合并对象
on:指定的合并依据的联结键列
how:选择合并的方式,'left'表示左侧数据框行数不可改变,只能由右边适应左边;'right'与之相反;'inner'表示取两个数据框联结键列的交集作为合并后新数据框的行;'outer'表示以两个数据框联结键列的并作为新数据框的行数依据,缺失则填充缺省值
lsuffix:对左侧数据框重复列重命名的后缀名
rsuffix:对右侧数据框重复列重命名的后缀名
sort:表示是否以联结键所在列为排序依据对合并后的数据框进行排序,默认为False
left = pd.DataFrame({'A': ['A0', 'A1', 'A2'], 'B': ['B0', 'B1', 'B2'], 'D': ['D3', 'D4', 'D5']}, index=['K0', 'K1', 'K2']) right = pd.DataFrame({'C': ['C0', 'C2', 'C3'], 'D': ['D0', 'D2', 'D3']}, index=['K0', 'K2', 'K3'])
left
right
left.join(right,lsuffix='_left',rsuffix='_right')
left.join(right,on='D',rsuffix='_right',lsuffix='_left')
5.数据的重整
数据透视表是excel中一个很有名且很有用的功能,但是一旦excel中导入的数据集过于庞大,打开都废劲,更不用说生成数据透视表了,而这种时候Python中的与透视表相似的功能就非常有优势。
dataframe.pivot()
pivot()的一些参数:
index:字符串或对象,作为透视表的行标签
columns:字符串或对象,作为透视表的列标签
values:生成新数据框的值(即透视表的作用区域)
df = pd.DataFrame({'foo': ['one','one','one','two','two','two'] ,
'bar': ['A', 'B', 'C', 'A', 'B', 'C'],
'baz': [1, 2, 3, 4, 5, 6]})
df
df.pivot(index='foo',columns='bar',values='baz')
数据框中有多列数值时:
df['baz_new'] = df['baz']*2 df
df.pivot(index='foo',columns='bar')
利用stack()与unstack()来重整数据(这两种方法互逆):
df2 = df.pivot(index='foo',columns='bar')
stacked = df2.stack() stacked
stacked.unstack()
6.数据框的抽样筛选
利用df.sample()来对原数据框进行一定比例的随机抽取并打乱顺序,主要参数如下:
frac:返回的抽样行数占总行数的比例,若想进行全排列则设置为1
replace:采取放回还是不放回,默认不放回,即False
weights:根据axis的方向来定义该方向上的各行或列的入样概率,长度需与对应行或列的数目相等,当权重之和不为0时,会自动映射为和为1
a = [i for i in range(10)] df = pd.DataFrame({'A':a, 'B':a, 'C':a}) df
df.sample(frac=1)
细心的你会发现虽然我们成功得到了一个数据框按行的随即全排列,但是每一行的行index却依然和打乱前对应的行保持一致,如果我们利用行标号进行遍历循环,那么实际得到的每行和打乱之前没什么区别,因此下面引入一个新的方法,确保数据框打乱顺序后行标号重置:
df.sample(frac=1).reset_index(drop=True)
这时我们得到的新的数据框的行index就进行了重置,于是我们就能愉快的进行遍历等操作啦~
对sample的其他参数进行设置:
A = [random.randint(1,10) for i in range(10)] B = [random.randint(1,10) for i in range(10)] C = [random.randint(1,10) for i in range(10)] D = [random.randint(1,10) for i in range(10)] df = pd.DataFrame({'A':A, 'B':B, 'C':C, 'D':D}) df
df.sample(n=3,axis=1,weights=[0.1,0.2,0.4,0.3])
除了使用pandas自带的sample方法,我们还可以使用机器学习相关包sklearn中的shuffle()方法:
from sklearn.utils import shuffle a = [i for i in range(10)] df = pd.DataFrame({'A':a, 'B':a, 'C':a}) shuffle(df).reset_index(drop=True)
7.数据框的条件筛选
在日常数据分析的工作中,经常会遇到要抽取具有某些限定条件的样本来进行分析,在SQL中我们可以使用Select语句来选择,而在pandas中,也有几种相类似的方法:
方法1:
A = [random.randint(1,10) for i in range(10)] B = [random.randint(1,10) for i in range(10)] ss = ['重庆','四川','安徽','山东'] Add = [random.choice(ss,1)[0] for i in range(10) ] df = pd.DataFrame({'A':A, 'B':B, 'address':Add}) df
df[df['address'] == '四川']
还可以通过将多个条件用括号括起来并用逻辑符号连接以达到多条件筛选的目的:
df[(df['B']>=5)&(df['address'] == '重庆')]
方法2:
利用df.query()进行条件筛选:
df.query('A > 2 and address == {}'.format("'"+"安徽"+"'"))
8.数据框元素的去重
df.drop_duplicates()方法:
参数介绍:
subset:为选中的列进行去重,默认为所有列
keep:选择对重复元素的处理方式,'first'表示保留第一个,'last'表示最后一个,False表示全部删除
inplace:默认为False,即返回一个原数据框去重后的新数据框,True则返回原数据框去重后变更的数据框
df.drop_duplicates(subset='address')
9.分组与合计函数配合使用
分组方法df.groupby()一般与size(),count()等合计函数联合使用,以达到记录分组频数等功能:
A = [random.randint(1,10) for i in range(20)] B = [random.randint(1,10) for i in range(20)] ss = ['重庆','四川','安徽','山东'] Add = [random.choice(ss,1)[0] for i in range(20) ] df = pd.DataFrame({'A':A, 'B':B, 'address':Add}) df
df.groupby('address').size()
df.groupby('address').count()
10.用类似SQL中as的方法来重命名columns
df.rename(columns={'A':'a','B':'b','address':'Address'})
11.数据框的排序
df.sort_values()方法对数据框进行排序:
参数介绍:
by:为接下来的排序指定一列数据作为排序依据,即其他列随着这列的排序而被动的移动
df#原数据框
df.sort_values(by='address')
12.缺失值的处理
常用的处理数据框中缺失值的方法如下:
df.dropna():删去含有缺失值的行
df.fillna():以自定义的方式填充数据框中的缺失位置,参数value控制往空缺位置填充的值,method控制插值的方式,默认为'ffill',即用上面最近的非缺省值来填充下面的缺失值位置
df.isnull():生成与原数据框形状相同的数据框,数据框中元素为判断每一个位置是否为缺失值返回的bool型变量
df.notnull():与isnull()方法返回的值相反
'''创造含有缺失值的数据框'''
import pandas as pd left = pd.DataFrame({'A': ['A0', 'A1', 'A2'], 'B': ['B0', 'B1', 'B2'], 'D': ['D3', 'D4', 'D5']}, index=['K0', 'K1', 'K2']) right = pd.DataFrame({'C': ['C0', 'C2', 'C3'], 'D': ['D0', 'D2', 'D3']}, index=['K0', 'K2', 'K3']) token = left.join(right,lsuffix='_left',rsuffix='_right') token
token.dropna()
token.fillna(value=0)
token.fillna(method='ffill')
token.isnull()
token.notnull()
以上就是关于Python pandas数据框的基本操作,而对于更复杂的更自定义化的与SQL语言更接近的部分,我们之后会在进阶篇中提及。