分享

Pandas学习笔记(DataFrame基本操作)

 PlanBlank 2018-06-05

    对于生成的dDataFrame,下一步进行的是对他的基本操作,增、减、改、查。

一. 数据选取

    从已有的DataFrame中取出其中一列或几列,并对其进行操作。

    Pandas取出DataFrame的列有两种方式,两个方式没有好与坏之分,还是看个人喜欢用哪个

  1. #-*- coding:utf-8 -*-  
  2. import pandas as pd  
  3.   
  4. df = pd.DataFrame({'goods':['coke cola', 'eggplant','condom'], 'quantity':[12,3,1], 'price':[20,12,80]})  
  5. df['goods']     #选择df的goods这一列  
  6.   
  7. df.goods         #同上,是选择列的第二种方法  
    需要注意的是,第一种方法看似像是一种列表形式,但是如果像是如下方式书写代码会报错

  1. df['goods','quantity']     #会报错,不要妄想通过这种方式获取多列。  
   上方的形式会引发一个KeyError的错误。如果想通过第一种形式获取多列,正确的形式如下

  1. df[['goods','quantity']]  
    将多列的列名按照一个list的形式传入,就可以获取一个DataFrame的多列。

二. 数据筛选

    往往选取出几个DataFrame的列并不能满足筛选,DataFrame的筛选的形式比较特殊,对列进行筛选时用到的是之前所讲的第二种选取列的形式,有点像是把列名视为一个DataFrame的属性。

  1. #-*- coding:utf-8 -*-  
  2. import pandas as pd  
  3.   
  4. df = pd.DataFrame({'goods':['coke cola', 'eggplant','condom'], 'quantity':[12,3,1], 'price':[20,12,80]})  
  5. print df[df.goods =='eggplant']     #      goods  price  quantity  
  6.                                      # 1  eggplant     12         3  
    上面代码的意思是选取DataFrame中,goods列的值为'eggplant‘的所有行。DataFrame中也支持多条件筛选,与Python的判断语句相同,and、or、not 和 xor分别代表 和、或、非、抑或。也可以用符号代替 &、|、~、^。每个判断条件要用圆括号括起来,否则会报错

  1. df[(df.goods =='eggplant') & (df.quantity == 12)]   
    选取df中 goods列值为 eggplant且 对应的 quantity值为12的所有列。

    在筛选数据时候也可以使用loc和iloc函数实现子集的选取,意思并不是说上方的筛选语句不对,亲测同样很好用,而且代码简单了点。loc和iloc进行数据筛选的格式如下:

  1. df = df.loc[df.goods=='eggplant', :]  
.loc[]相当于是把想要筛选的列通过 ':'全部选出来。loc方法同样支持多条件筛选。
  1. df = df.loc[(df.goods =='eggplant') & (df.quantity == 12), :]   
    loc形式的多条件筛选,条件与条件之间同样要使用括号分割开。这两行loc方法筛选的结果与之前没用loc方法写的代码效果是一样的,格式规范而言肯定是有loc的更容易让人理解。但是如果只是给自己写脚本完全可以用前一种,必要时候做个注释即可。

    条件筛选的另一种形式,就是选取一个DataFrame中满足条件的行的某几列(并不是全部列)。此时只需将上面的代码做一小点改变即可。

  1. df = df.loc[(df.goods =='eggplant') & (df.quantity == 12), ['goods', 'price']]  
   此时亲测使用loc方式会比较好一些,因为之前loc形式后方的 ':' 代表的是满足条件的全部行的所有列的数据,一个冒号囊括了所有列。此时要是指定其中的某几列,通过list的形式,list的元素是DataFrame的列名,元素类型是字符串。上方的代码所表达的是满足条件的所有行的 goods 和 price 两列。


三. 数据的修改

    数据的修改往往有这几种形式 ① 针对某个值或者某个范围的值的修改。  ② 增加列、删除列  ③ 增加行、删除行  ④修改索引  ⑤修改列名

    数据值的修改常见于分类的问题中,比如将一个列作为分类的列,有时候往往该列的值不是想要的数字表示的不同分类,或者更复杂是一个连续变量,此时针对DataFrame的修改就格外重要。

添加列

  1. df['price'][df.price > 15] = 'expensive'  
    通过这一行代码,就将df的 price 一列的大于15的商品定义为 ‘expensive’。分类问题中不同的类常常用不同的数字来表示,而不同类之间的转换需要的就是这样的筛选与修改。

    增加列的方法很简单,而且很常用,比如想要在之前的df中添加一个叫‘remain’的列,记录是否有货,可以直接使用下面的代码:

  1. df['remain'] = 'yes'  
这样就在之前的df后面又加了一列‘remain’,但是这一整列的值为‘yes’。如果不想在末尾加列,而是想在某列之间添加一列,那么就需要使用insert方法。

  1. df.insert(int=0, column = 'remain', value='yes')  
    int参数传入的是一个整数,这个整数是插入列所在的位置,0代表列的索引为0的位置,也就是第一列。 column参数是设置列名。 value值是给这列赋值,可以是字符串,如果是字符串,那么这一列的值都会是这个字符串;也可以是Pandas的Series,或者是Python的list。这样可以使得这一整列不是同一个值。

删除列

    列的删除使用Pandas模块中的drop()方法最为高效。假如要删除刚才添加的remain列。

  1. df.drop(labels='remain', axis=1, inplace=True)  
上方这行代码会成功删除DataFrame中的‘remain’列,注意:如果inplace参数不指定为True,只会在内部删除,df并不会被真正改变。axis参数默认是0,也就是代表着行,所以删除列时要把axis改为1

如果想删除df中多个列,drop()方法也是可以的。

  1. df.drop(labels=['remain', 'quantity'], axis=1, inplace=True)  
将想删除的多个列名以Python的列表形式传给labels参数,就可以在该数据框中删除列表中的列。

添加行

    Pandas的添加行方式有很多种不过最为直观的方式是这样的

  1. df.loc[3]={'goods':'shampoo','quantity':13, 'price':50}  
    loc又出现,在索引为3的行(第四行)插入一组数据。数据的形式按照字典的形式传入。还有一种方法是通过append方法。

  1. df = df.append({'goods':'shampoo','quantity':13, 'price':50}, ignore_index=True)  
    也是使用dict形式传入。

删除行

  1. df.drop(labels = 1, axis=0,inplace = True)  
删除索引为1的行,axis=0表示横向删除行。删除多行时,传入labels的参数是一个list,元素是列的索引值。

  1. df.drop(labels = [1, 4, 6], axis=0,inplace = True)  
删除df中的索引为1,4,6的行。

修改索引

    修改索引有两种情况,改变索引和不改变索引。

① 不改变索引,可以看做是将原始数据按照索引顺序排序

  1. df.sort_index(axis=1,ascending=False)  
    axis表示所有列都随着索引一起变位置,ascending是降序的意思,默认是False。

② 改变索引

set_index()方法

  1. df.set_index(keys='goods',inplace=True)  
    将df的goods这一列设置成索引,在原数据框中改。这个方法感觉更适合之前没有索引的情况下。当之前设置了索引的情况下需要的是reindex方法。

  1. df.reindex(new_index,axis=0)  

    new_index可以是Python列表,元素是现在已有的索引的一部分值,这个方法常常用于保留想留下的行

修改列名

    修改列名需要用到的是rename()方法。

  1. dynamic_RNApol.rename(columns={'d0': 'rnapol_d0', 'd1': 'rnapol_d1', 'd3': 'rnapol_d3', 'd5': 'rnapol_d5', 'd7': 'rnapol_d7','d11': 'rnapol_d11', 'd15': 'rnapol_d15', 'd18': 'rnapol_d18', 'ipsc': 'rnapol_ipsc'}, inplace=True)  
  1.   
    这就是rename改变列名的用法,传入的形式是字典,键值是新名字;value值是原本的列名。这样的好处是做到了一一对应。之后一定要加上inplace参数,设置为TRUE,否则不会在原有的dataframe中改动。

数据类型转化

    dataframe中的astype()方法是对数据类型进行转换的函数。以一个例子进行说明

  1. df = pd.DataFrame({'id': range(4), 'age': ['13', '34', '23'], 'weight': ['45.7', '60.9', '55.5']})  
  2. df.dtypes  
    dtype的结果会显示出,id列的数据类型是 int, 而age和weight列的数据类型都是 object。现在将age转化为 int类型,weight转化为float类型。此时astype函数的作用就有所体现。

  1. df.astype({'age':'int', 'weight':'float'})  
  1. valid['distance'] = valid['distance'].astype('int')  


   通过字典的形式传入,将两列转换成了想要的数据类型。

数据排序

    dataframe中索引排序用到的是sort_index方法,相似的列数值排序运用的是sort_values()方法。

  1. df.sort_values( by=['age'], ascending=False, inplace=True)  #只通过age进行排序;升序;如有缺失值放在最后。  
  2. df.sort_values(by=['age', 'weight'], ascending=True, inplace=True, na_position='first') #先通过age排序,在其基础上通过weight排序;降序,缺失值放在最前方。  
    数据的排序在实际问题中很有用,比如找出聚类中得分最高的几个项等等。

数据去重

    在dataframe中去除重复,使用drop_duplicates()方法。而只是检查dataframe中是否出现重复有的是duplicated方法,如果只是想检查某列中是否存在重复的值可以通过subset参数将列传入到duplicated()方法中。

  1. df.duplicated()  #检查整个dataframe中是否出现重复  
  2. df.duplicated(subset='age')  #检查age这列是否出现重复数据  
  3. df.drop_duplicates()  #删除dataframe中的重复  
    其中,subset参数传入的可以是单一的列名;同时也可以是多个列名组成的list。

四. dataframe基本操作

数据抽样

    dataframe的抽样直接使用sample()方法进行,抽样在涉及到统计学算法的时候很有用,所以先了解一下这个方法的参数。

  1. df.sample(n=5, replace=False)  
  2. df.sample(frac=0.2, replace=True)  
    这两种是最常用的形式,n参数是直接指定抽多少个样本,frac参数则是一个0到1之间的浮点数,指定的是抽取的样本占多大比例。replace表示是否是有放回的抽取,默认是FALSE。weight参数在这里没体现,这个参数是当样本具有权重时候所用的,weight参数后面加的是列名,未赋值则每列的权重默认为0,如果要赋值权重,所有权重的和为1,如果和不为1,则自动进行归一化处理。

频率统计

    dataframe中,统计某列不同的值出现的次数使用value_counts()方法。

  1. df = pd.DataFrame({'id': range(4), 'name': ['Jack', 'Craig', 'Chuck', 'Jack'],'gender': ['M', 'M', 'M', 'F'] , 'age': ['13', '34', '23','4'], 'weight': ['45', '60', '55', '30']})  
    可以看到上面的dataframe中,name列有重名的,现在要统计不同的名字出现的次数。
  1. df.name.value_counts()  
    上面的代码反悔的结果是在这个dataframe中,不同的名字出现的次数。

    value_counts()方法的一个妙用是用于求占比,假如现在要求的是性别的占比。

  1. df.gender.value_counts()/ sum(df.gender.value_counts)  
    这行代码返回的是不同性别人数除以总人数所得到的个性别的占比。但是value_counts()方法只能是单变量的计数。如果想设置一个条件后在进行计数,可以使用的是crosstab()方法。

  1. pd.crosstab(index=df.name, columns=df.gender)  
    这行代码,记录的是不同名字出现的次数,但是将性别分开讨论。columns参数可以传入多个列,传入形式是list,元素是列名。注意:columns传入的列必须是离散型变量,用途是用于分类

缺失值处理

① 缺失值的检查

    检查缺失值所用的函数是isnull(),这看起来和MySQL中的差不多。

  1. print any(df.isnull(), '\n')  
    检查整个dataframe中是否存在缺失值。
  1. is_null = []  
  2. for col in df.columns:  
  3.     is_null.append(any(pd.isnull(df.col)))  

    这是检查dataframe每行是否有缺失值。

  1. is_null = []  
  2. for index in list(df.index):  
  3.     is_null.append(any(pd.isnull(df.loc[index, :])))  

    同理。is_null方法也可以对每列进行缺失值检查。is_null方法返回的是一个布尔值,True表示有缺失值,False表示没有缺失值。

② 缺失值的删除
    这是一种比较极端的方法,通过dropna()方法,这个方法的使用有两种形式。

  1. df.dropna()  
    这种方式是将有缺失值的行全部删除。如果在缺失值较多的情况下,数据的量会大打折扣。

  1. df.dropna('all')  
    这个是第二种形式,‘all’指明了删除的行是所有值都为缺失值的情况,因为数据中缺失一些数据是很常见的,只删除全部字段都为空的变量才能真正的保留更多的数据。
③ 缺失值的填补
    使用fillna()方法可以对dataframe进行缺失值的填补。
  1. df.fillna(0, inplace=True)  #最简单的一种方式,缺失值统一以一个值进行填补  
  2. df.fillna(value={'id': 0, 'name': 'No', 'gender': 'unknown', 'age':'unknown', 'weight': 0}, inplace=True)  #针对不同的列设置不同的缺失填补值  
  3. df.fillna(method='ffill', inplace=True)  #用上一行的值对自身进行填补  
  4. df.fillna(method='bfill', inplace=True)  #用后一行的值对自身进行填补  
  5. df.fillna({'age': df.age.mean(), 'weight': df.weight.max()}, inplace=True)  #用不同列的极值,均值,中位数等进行缺失值填补。  


数据映射
    看见映射,想到的首先是Python中的map()函数,相比于一般的for循环,map函数具有极高的效率。在日常的Python编程中,map()方法所传入的是一个函数和一个序列,这个函数会相继作用于序列中的每一个元素。得到的是一个新的序列。dataframe也是一个特殊的可遍历序列,但是dataframe的映射所用的是apply()方法。

  1. is_null = []  
  2. for index in list(df.index):  
  3.     is_null.append(any(pd.isnull(df.loc[index])))  
现在要挑战for循环,将原本的检查每行是否有缺失值的for循环改成apply()形式。
  1. isnull = lambda x : any(pd.isnull(df.loc[x,:]))  
  2. is_null = df.apply(func=isnull, axis=1)  
func参数是所用的方法,这里的方法是之前设定的lambda函数。axis参数0代表映射到各列,而1代表着映射到每行。
    numpy的某些方法也能通过apply()形式作用于dataframe上,比如说现在有一个dataframe里面记录的是学生的各科成绩(第一列到第五列),现在要计算每个学生的均分,和每个科目的中位数。
  1. df['average'] = df.iloc[:, 0:5].apply(func=np.mean, axis=1)  
  2. df.iloc[:, 0:5].apply(func=np.median, axis=0)  







  1.   



                                    

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约