Python数据科学—pandas数据包

发布时间: 2022.02.22 浏览: 0 发布者: 慕柏生物

一、pandas包基础简介二、pandas处理缺失值1.发现缺失值2.剔除缺失值3.填充缺失值三、层级索引1.显式地创建多级索引2.多级索引行列转换1.有序和无序的索引2.索引stack和unstack3.索引的设置   四、合并数据集:concat与append操作       1.通过pd.concat实现简易合并       2.类似join的合并       3.append()方法   五、累计与分组       1.pandas的累计方法       2.group.by应用           1.过滤           2.转换

一、pandas包基础简介

pandas属于python下的一种数据分析包,最初是应用于金融数据分析工具而开发出来的,因此pandas为时间序列分析提供了很好的支持,pandas 纳入了大量库和一些标准的数据模型,提供了高效地操作大型数据集所需的工具。pandas提供了大量能使我们快速便捷地处理数据的函数和方法。你很快就会发现,它是使python成为强大而高效的数据分析环境的重要因素之一。

二、pandas处理缺失值

isnull()   #创建一个人布尔类型的掩码标签缺失值
notnull()  #与isnull操作相反
dropna()   #返回一个剔除缺失值的数据
fillna()   #返回一个填充了缺失值的数据副本

1.发现缺失值

pandas数据结构有二种有效方法可以发现缺失值:isnull()和notnull()。每种方法返回布尔类型的掩码数据,例如:

IN[1]:data = pd.series([1,nap.nan,'hello'.None])
IN[1]:data.isnull()
Out[1]: 0 False
         1 True
         2 False
         3 True
         dtype: bool

布尔类型掩码数组可以直接作为series或者DataFrame的索引使用。

IN[2]: data[data.notnill()]
Out[2]: 0 1
         2 hello
         dtype: object

在series里使用的insull()和notnull同样适用于DataFrame,产生的结果同样是布尔类型。

2.剔除缺失值

使用dropna()(剔除缺失值)和fillna()(填充缺失值)。

IN[3]: data.dropma()
OUT[3]: 0 1
         2 hello
         dtype: object
#将有缺失值的行全部剔除,默认情况下dropna()会剔除任何包含缺失值的整行数据
#可以设置接不同的坐标轴别除缺失值,比如axts=1(或axis='coLumns')会剔除#任何#包含缺失值的整列数据
#这么做也会把非缺失值一并别除,因为可能有时候只需剔除全部是缺失值的行或列,或者绝大多数是缺失值的行或列。这些需求可以通过设置how或thresh参数来满足,它们可以设置剔除行或列缺失值的数量阀值
#默认设置是how=any,也就是说只要有缺失值就剔除整行或整列(通过axts设置坐标)。你还可以设置how=all就只会剔除全部是缺失值的行或列
#还可以通过thresh参数设置行或者列中非缺失值的最小数量,从而实现更加个性化的配置

3.填充缺失值

当不想移除缺失值,而是想替换成有效数值。不仅可以通过isnull()方法建立掩码填充缺失值,但是pandas为此专门提供了一个fillna()方法,他将返回填充了缺失值后的数值副本。

IN[4]: data
OUT[4]: a 1.0
        b NaN
        c 2.0
        d NaN
        e 3.0

#使用单独的值来填充缺失值,例如用5:
IN[5]:data.fillna(5)
OUT[5]: a 1.0
        b 5.0
        c 2.0
        d 5.0
        e 3.0

#可以用缺失值前面的有效值来从前往后填充(forward-fill):
IN[6]: data.fillna(method='ffill')
OUT[6]: a 1.0
        b 1.0
        c 2.0
        d 2.0
        e 3.0

#可以用缺失值后面的有效值来从后往前填充(back-fill):
IN[7]: data.fillna(method='bfill')
OUT[7]: a 1.0
        b 2.0
        c 2.0
        d 3.0
        e 3.0

三、层级索引

1.显式地创建多级索引

你可以用pd.MultiIndex中的类方法更加灵活地构建多级索引.例如,你可以通过一个有不同等级的若干简单数组组成的列表来构建MultiIndex:

IN[8]pd.MultiIndex.from_arrays([['a','a','b','b'],[1,2,1,2]])
OUT[8]: MultiIndex(levels=[['a','b'],[1,2]]
                   labels=[[0,0,1,1],[0,1,0,1]])

也可以通过包含多个索引值的元组构成的列表创建MultiIndox;

IN[9]pd.MultiIndex.from_tuples([('a',1),('a',2),('b',1),('b',2)])
OUT[9]: MultiIndex(levels=[['a','b'],[1,2]]
                   labels=[[0,0,1,1],[0,1,0,1]])

还可以用两个索引的笛卡尔积(Cartesian product)创建MultiIndex:

IN[10]pd.MultiIndex.from_product([['a','b'],[1,2]])
OUT[10]: MultiIndex(levels=[['a','b'],[1,2]]
                   labels=[[0,0,1,1],[0,1,0,1]])

更可以直接提供levels(包含每个等级的索引值列表的列表)和labels(包含每个索引值标签列表的列表)创建MultiIndex:

IN[11]pd.MultiIndex(levels=[['a','b'],[1,2]],
                    labels=[[0,0,1,1],[0,1,0,1]])     
OUT[11]:MultiIndex(levels=[['a','b'],[1,2]],
                    labels=[[0,0,1,1],[0,1,0,1]])     

2.多级索引行列转换

使用多级索引的关键是掌握有效数据转换的方法。Pandas提供了许多操作,可以让数
据在内容保持不变的同时,按照需要进行行列转换。

1.有序和无序的索引

注意! 如果MultiIndex不是有序的索引,那么大多数切片操作都会失败。,为此pandas提供了许多便捷的操作完成排序,如sort_index()和sortlevel()方法。

IN[12]index = pd.MultiIndex.from_product([['a','c','b'],[1,2]])
     data = pd.series(np.random.rand(6),index=index)
     data.index.names = ['char','int']
     data = data.sort_index()
     data

OUT[12]:char int
          a    1    0.003001
               2    0.164974
          b    1    0.001693
               2    0.526226
          c    1    0.741650
               2    0.569264

#再使用局部切片
IN[13]: data['a':'b']
OUT[13]: char int
         a    1    0.003001
              2    0.164974
         b    1    0.001693
              2    0.526226
2.索引stack和unstack
IN[14]: pop.unstack(level=0)
OUT[14]: state    California    New York    Texas
         year
         2000     33871648      18976457    20851820
         2010     37253956      19378102    25145561

IN[15]: pop.unstack(level=1)
OUT[15]: year          2000           2010
         state
         California    33871648       37253956
         New York      18976457       19378102
         Texas         20851820       25145561

#unstack()是stack()的逆操作,同时使用这2种方法让数据保持不变。
3.索引的设置

层级数据维度转换的另一种方法是行列标签转换,可以通过reset_index方法实现。如果在上面的人口数据series中使用该方法,则会生成一个列标签中包含之前行索引标签state和year的DataFrame。也可以用数据的name属性为列设置名称:

IN[16]: pop_flat = pop.reset_index(name='population')
        pop_flat
OUT[16]:        state    year    population
        0   California  2000    33871648
        1   California  2010    37253956
        2   New York    2000    18976457
        3   New York    2010    19378102
        4   Texas       2000    20851820
        5   Texas       2010    25145561

四、合并数据集:concat与append操作

1.通过pd.concat实现简易合并

pandas语法和np.concatenate语法类似,但是配置参数更多,功能也更强大:

IN[17]: x = make_df('AB', [0,1])

pd.concat(objs, axis=0, join='outer', join_axes=None, ignore_index=False,keys=None,
          levels=None, names=None, verify_integrity=False,copy=True)

pd.concat()可以简单地合并一维的series或者DataFrame对象,也可以用来合并高维数据,默认情况下,DataFrame的合并都是逐行进行的(默认设置是axies=0),也可以自行设置合并坐标轴。
1.索引重复
np.cocatenate与pd.concat最主要的差异之一就是Panas在合并时会保留索引,即使索引是重复的!例如下面的简单示例:

IN[18]: x = make_df('AB', [0,1])
      y = make_df('AB', [2,3])
      y.index = x.index #复制索引
      print(x); print(y); print(pd.concat[x, y])
x           y           pd.concat([x, y])
    A   B       A   B       A   B
0   A0  B0  0   A2  B2  0   A0  B0
1   A1  B1  1   A3  B3  1   A1  B1
                        0   A2  B2 
                        1   A3  B3
#此时可以发现结果中索引值为重复的,pd.concat()为此提供了一些解决的方案。

1)忽略索引
有时索引无关紧要,那么合并时就可以忽略它们,可以通过设置ignore_index参数来实现。
如果将参数设置为True,那么合并时将会创建一个新的整数索引。

IN[19]: print(x); print(y); print(pd.concat([x, y], ignore_index=True))
x           y           pd.concat([x, y], ignore_index=True)
    A   B       A   B       A   B
0   A0  B0  0   A2  B2  0   A0  B0
1   A1  B1  1   A3  B3  1   A1  B1
                        2   A2  B2 
                        3   A3  B3

(2)增加多级索引
还可以通过keys参数为数据源设置多级索引标签,这样结果数据可以带上多级索引
IN[20]: print(x); print(y); print(pd.concat([x, y], ignore_index=True))
x           y           pd.concat([x, y], keys=['x''y'])
    A   B       A   B       A   B
0   A0  B0  0   A2  B2  0   A0  B0
1   A1  B1  1   A3  B3  1   A1  B1
                        0   A2  B2 
                        1   A3  B3
2.类似join的合并

前面合并的都是同样列名的dataframe,但是在日常工作中往往会需要合并不同列名的数据,而pd.concat提供了一些选项来解决这些问题,例如:

IN[21]: df5 = make_df('ABC', [12]) 
        df6 = make_df('ABC', [34])
        print(df5); print(df6); print(pd.concat([df5, df6])

df5             df6                 pd.concat([df5, df6])
    A   B   C       B   C   D           A   B   C   D   
1   A1  B1  C1  3   B3  C3  D3      1   A1  B1  C1  NaN
2   a2  b2  c2  4   B4  C4  D4      2   A2  B2  C2  NaN
                                    3  NaN  B3  C3  D3
                                    4  NaN  B4  C4  D4  

默认情况下,某个位置上缺失的数据会用NaN表示。如果不想这样,可以用join和join_axes参数设置合并方式。默认的合并方式是对所以输入列进行并集合并(join='outer'),当然也可以用join='inner'实现对输入列的交集合并:
IN[21]: print(df5); print(df6);
        print(pd.concat([df5, df6], join='inner'))

df5             df6                 pd.concat([df5, df6],join='inner')
    A   B   C       B   C   D            B   C   
1   A1  B1  C1  3   B3  C3  D3      1    B1  C1  
2   a2  b2  c2  4   B4  C4  D4      2    B2  C2  
                                    3    B3  C3  
                                    4    B4  C4  

#另一种合并方式是直接确定结果使用的列名,设置join_axes参数,里面是索引对象构成的列表(是列表的列表)。将结果的列名设置为第一个输入的列名:
IN[22]: print(df5); print(df6);
        print(pd.concat([df5, df6], join_axes=[df5.columns]))
df5             df6                 pd.concat([df5, df6],join_axes=[df5.columns]])
    A   B   C       B   C   D           A   B   C     
1   A1  B1  C1  3   B3  C3  D3      1   A1  B1  C1 
2   a2  b2  c2  4   B4  C4  D4      2   A2  B2  C2 
                                    3  NaN  B3  C3 
                                    4  NaN  B4  C4  
3.append()方法

因为直接进行数组合并的需求非常普遍,所以Series和DataFrame对象都支持append方法,让你通过最少的代码实现合并功能。例如,你可以使用df1.append(df2),效果与pd.concat([df1,df27)一样:

IN[23]: print(df1); print(df2);print(df1.append(df2))
df1             df2                 df1.append(df2)
    A   B          A   B               A   B   
1   A1  B1    3   A3  A3        1    A1   B1  
2   a2  b2    4   A4  A4        2    A2   B2  
                                3    A3   B3  
                                4    A4   B4  

需要注意的是、与Python列表中的append()和extend()方法不同,Pandas的append()不直接更新原有对象的值,而是为合并后的数据创建一个新对象。因此,它不能被称之为一个非常高效的解决方案,因为每次合并都需要重新创建索引和数据缓存。总之,如果你需要进行多个append操作,还是建议先创建一个DataFrame列表,然后用concat()函数一次性解决所有合并任务。

五、累计与分组

1.pandas的累计方法

指标描述
count()计数项
first()第一项和最后一项
mean(),median()均值与中位数
min(),max()最小值与最大值
std(),var()标准差与方差
mad()均值与绝对差
prod()所有项乘积
sum()所有项求和

2.group.by应用

1.过滤

可以按照分组的属性丢弃若干数据。例如我们可能只需要保留超过标准差超过某个阈值的组:

IN[24]:
def filter_func(x):
    return x['data2'].std()>4
print(df); print(df.groupby('key').std());
print(df.groupby('key').filter(filter_func))
df                              df.groupby('key').std()
    key   data1   data2           key     data1    data2
0    A       0       5            A     2.12132    1.414214         
1    B       1       0            B     2.12132    4.949747
2    C       2       3            C     2.12132    4.242641
3    A       3       3
4    B       4       7
5    C       5       9
df.groupby('key').filter(filter_func)
    key     data1   data2
1   B       1       0
2   C       2       3      
4   B       4       7
5   C       5       9
#filter()函数会返回一个布尔值,表示每个组是否通过过滤。由于A组'data2'列的标准差不大于4,所以被丢弃。
2.转换

累计操作返回的是对组内全量数据缩减过的结果,而转换操作会返回一个新的全量数据。数据经过转换之后,其形状与原来的输入数据是一样的。常见的例子就是将每组的样本数据减去各组的均值,实现数据标准化:

IN[25]:df.groupby('key').transform(lambda x: x - x.mean())
OUT[25]:      data1       data2
        0   -1.5        1.0
        1   -1.5       -3.5
        2   -1.5       -3.0
        3   -1.5       -1.0
        4   -1.5        3.5 
        5   -1.5        3.0

参考文献

《python数据科学手册》 Jack Vanderplas[美]