美文网首页Python数据分析
python数据分析之Pandas数据统计/分组/连接/清洗/重

python数据分析之Pandas数据统计/分组/连接/清洗/重

作者: 雪飘千里 | 来源:发表于2018-07-27 21:48 被阅读0次

    统计计算和描述

    常用的统计计算:
    sum、mean、max、min
    axis=0 按列统计,axis=1 按行统计(axis=0时,表示最后的数据是一行,所以需要按列统计,axis=1时,表示最后的数据是一列,所以需要按行统计)


    image.png
    image.png
    df_obj = pd.DataFrame(np.random.randn(5,4), columns = ['a', 'b', 'c', 'd'])
    print(df_obj)
    
    df_obj.sum()
    df_obj.max()
    df_obj.min(axis=1)
    # 统计描述
    df_obj.describe()
    
    

    层级索引
    1、MultiIndex对象
    2、选取子集
    外层选取 ser_obj['outer_label']
    内层选取 ser_obj[:,'inner_label']
    3、常用于分组操作、透视表的生成等
    4、交换分层顺序 swaplevel()
    5、排序分层 sortlevel()

    import pandas as pd
    import numpy as np
    
    ser_obj = pd.Series(np.random.randn(12),
                        index=[['a', 'a', 'a', 'b', 'b', 'b', 'c', 'c', 'c', 'd', 'd', 'd'],
                               [0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2]])
    print(ser_obj)
    # MultiIndex索引对象
    print(type(ser_obj.index))
    print(ser_obj.index)
    
    #选取子集
    print(ser_obj['c'])   # 外层选取
    print(ser_obj[:, 2])   # 内层选取
    
    # 交换分层顺序
    print(ser_obj.swaplevel())
    
    #交换并排序分层
    print(ser_obj.swaplevel().sortlevel())
    

    分组与聚合 GroupBy对象

    1、对数据集进行分组,然后对每组进行统计分析
    2、SQL能够对数据进行过滤,分组聚合
    3、pandas能利用groupby进行更加复杂的分组运算
    4、分组运算过程(和Hadoop的mapreduce类似)
    split -> apply ->combine
    拆分:进行分组的依据
    应用:每个分组运行的计算规则
    合并:把每个分组的计算结果合并起来

    import pandas as pd
    import numpy as np
    
    dict_obj = {'key1' : ['a', 'b', 'a', 'b', 
                          'a', 'b', 'a', 'a'],
                'key2' : ['one', 'one', 'two', 'three',
                          'two', 'two', 'one', 'three'],
                'data1': np.random.randn(8),
                'data2': np.random.randn(8)}
    df_obj = pd.DataFrame(dict_obj)
    print(df_obj)
    
    #GroupBy对象,DataFrameGroupBy,SeriesGroupBy
    # dataframe根据key1进行分组
    print(type(df_obj.groupby('key1')))
    # data1列根据key1进行分组
    print(type(df_obj['data1'].groupby(df_obj['key1'])))
    
    # 分组运算
    grouped1 = df_obj.groupby('key1')
    print(grouped1.mean())
    
    grouped2 = df_obj['data1'].groupby(df_obj['key1'])
    print(grouped2.mean())
    
    # size(),返回每个分组的元素个数
    print(grouped1.size())
    print(grouped2.size())
    
    # 按列名分组
    df_obj.groupby('key1')
    
    # 按自定义key分组,列表
    self_def_key = [1, 1, 2, 2, 2, 1, 1, 1]
    df_obj.groupby(self_def_key).size()
    
    # 按自定义key分组,多层列表
    df_obj.groupby([df_obj['key1'], df_obj['key2']]).size()
    
    # 按多个列多层分组
    grouped2 = df_obj.groupby(['key1', 'key2'])
    print(grouped2.size())
    
    #GroupBy对象分组迭代
    # GroupBy对象支持迭代操作,每次迭代返回一个元组( group_name, group_data)
    for group_name, group_data in grouped2:
        print(group_name)
        print(group_data)
    
    # GroupBy对象转换list
    list(grouped1)
    
    # GroupBy对象转换dict
    dict(list(grouped1))
    
    # 按列分组
    print(df_obj.dtypes)
    
    # 按数据类型分组
    df_obj.groupby(df_obj.dtypes, axis=1).size()
    df_obj.groupby(df_obj.dtypes, axis=1).sum()
    
    

    聚合aggregation

    dict_obj = {'key1' : ['a', 'b', 'a', 'b', 
                          'a', 'b', 'a', 'a'],
                'key2' : ['one', 'one', 'two', 'three',
                          'two', 'two', 'one', 'three'],
                'data1': np.random.randint(1,10, 8),
                'data2': np.random.randint(1,10, 8)}
    df_obj5 = pd.DataFrame(dict_obj)
    print(df_obj5)
    
    # 内置的聚合函数
    print(df_obj5.groupby('key1').sum())
    print(df_obj5.groupby('key1').max())
    print(df_obj5.groupby('key1').min())
    print(df_obj5.groupby('key1').mean())
    print(df_obj5.groupby('key1').size())
    print(df_obj5.groupby('key1').count())
    print(df_obj5.groupby('key1').describe())
    
    # 自定义聚合函数,传入agg方法中
    def peak_range(df):
        """
            返回数值范围
        """
        #print type(df) #参数为索引所对应的记录
        return df.max() - df.min()
    
    print(df_obj5.groupby('key1').agg(peak_range))
    print(df_obj5.groupby('key1').agg(lambda df : df.max() - df.min()))
    
    # 应用多个聚合函数
    
    # 同时应用多个聚合函数
    print(df_obj5.groupby('key1').agg(['mean', 'std', 'count', peak_range])) # 默认列名为函数名
    print(df_obj5.groupby('key1').agg(['mean', 'std', 'count', ('range', peak_range)])) # 通过元组提供新的列名
    
    # 每列作用不同的聚合函数,使用dict
    dict_mapping = {'data1':'mean',
                    'data2':'sum'}
    print(df_obj5.groupby('key1').agg(dict_mapping))
    dict_mapping = {'data1':['mean','max'],
                    'data2':'sum'}
    print(df_obj5.groupby('key1').agg(dict_mapping))
    

    数据分组运算

    聚合运算改变了原始数据的shape,那么如何保持原始数据的shape呢
    1、使用merge的外连接,比较复杂
    2、使用 transform

    import pandas as pd
    import numpy as np
    # 分组运算后保持shape
    dict_obj = {'key1' : ['a', 'b', 'a', 'b', 
                          'a', 'b', 'a', 'a'],
                'key2' : ['one', 'one', 'two', 'three',
                          'two', 'two', 'one', 'three'],
                'data1': np.random.randint(1, 10, 8),
                'data2': np.random.randint(1, 10, 8)}
    df_obj = pd.DataFrame(dict_obj)
    
    # 按key1分组后,计算data1,data2的统计信息并附加到原始表格中
    k1_sum = df_obj.groupby('key1').sum()
    
    # 方法1,使用merge
    pd.merge(df_obj, k1_sum, left_on='key1', right_index=True)
    # 方法2,使用transform
    k1_sum_tf = df_obj.groupby('key1').transform(np.sum).add_prefix('sum_')
    df_obj[k1_sum_tf.columns] = k1_sum_tf
    df_obj
    # 自定义函数传入transform
    def diff_mean(s):
        """
            返回数据与均值的差值
        """
        return s - s.mean()
    
    df_obj.groupby('key1').transform(diff_mean)
    
    # apply 
    def top_n(df, n=3, column='APM'):
        """
            返回每个分组按 column 的 top n 数据
        """
        return df.sort_values(by=column, ascending=False)[:n]
    
    df_data.groupby('LeagueIndex').apply(top_n)
    

    数据清洗

    1、数据清洗是数据分析关键的一步,直接影响之后的处理工作
    2、数据需要修改么,有什么需要修改的么,数据应该怎么调整才能适用于借来的分析和挖掘?
    3、是一个迭代的过程,实际项目中可能需要不知一次地执行这些清洗操作
    4、处理缺失数据 pd.fillna(),pd.dropna()

    过滤
    • query过滤
    # age是列名
     df.query('age>20 & age<40')
    
    • loc 索引过滤
    df.loc[(df.age>20) & (df.color.notnull())]
    # 注意在逻辑操作符两边的过滤条件必须使用小括号括起来,否则条件过滤不起作用
    
    处理缺失数据
    • 1.对缺失值进行填充——fillna
      使用DataFrame.fillna(value=None, method=None, axis=None,)
      value: scalar, dict, Series, or DataFrame,dict 可以指定每一行或列用什么值填充
      method: {‘backfill’, ‘bfill’, ‘pad’, ‘ffill’, None}, default None
      在列上操作
      • ffill / pad: 使用前一个值来填充缺失值
      • backfill / bfill :使用后一个值来填充缺失值
    # 用值为x的数来对缺失值进行填充
    df.fillna(value=x)
    
    # 每一列使用不同的缺失值
    values = {'A': 0, 'B': 1, 'C': 2, 'D': 3}
    df.fillna(value=values)
    
    # 使用后边或前边的值填充缺失值
    df.fillna(method='ffill')
    df.fillna(method='bfill')
    
    
    • 2.去掉包含缺失值的行
      使用DataFrame.dropna(axis=0, how='any', thresh=None, subset=None, inplace=False)
      参数说明:
      • axis:
        axis=0: 删除包含缺失值的行
        axis=1: 删除包含缺失值的列
      • how: 与axis配合使用
        how=‘any’ :只要有缺失值出现,就删除该行货列
        how=‘all’: 所有的值都缺失,才删除行或列
      • thresh: axis中至少有thresh个非缺失值,否则删除
        比如 axis=0,thresh=10:标识如果该行中非缺失值的数量小于10,将删除改行
      • subset: list
        在哪些列中查看是否有缺失值
      • inplace: 是否在原数据上操作。如果为真,返回None否则返回新的copy,去掉了缺失值
    # 去掉所有包含缺失值的行——dropna
    df.dropna(how='any')
    # 在指定'name', 'born'列中如有缺失值,则删除对应的行
    df.dropna(subset=['name', 'born'])
    # 如果行中非缺失值的数目小于2个,则删除该行
    df.dropna(thresh=2)
    
    • 3.删除行 或者 列——drop
      可以使用dropna 或者drop函数
      DataFrame.drop(labels=None, axis=0, index=None, columns=None, level=None, inplace=False, errors='raise')
      参数说明:
      • labels: 要删除行或列的列表
      • axis: 0 行 ;1 列
      • columns:要删除的列
    # 删除B,C两列
    df.drop(columns=['B', 'C'])
    # 删除行(索引)
    df.drop([0, 1])
    

    数据连接 merge

    1、根据单个或多个键将不同的DataFrame的行连接起来
    2、类比sql join操作
    3、默认将重叠列的列名作为“外键”进行连接
    on 显式的指定 “外键”
    left_on 左侧数据的外键
    right_on 右侧数据的外键
    4、默认是 “内连接”(inner),即结果中的键是交集

    import pandas as pd
    import numpy as np
    
    df_obj1 = pd.DataFrame({'key': ['b', 'b', 'a', 'c', 'a', 'a', 'b'],
                            'data1' : np.random.randint(0,10,7)})
    df_obj2 = pd.DataFrame({'key': ['a', 'b', 'd'],
                            'data2' : np.random.randint(0,10,3)})
    
    # 默认将重叠列的列名作为“外键”进行连接,默认是 “内连接”(inner)
    #这里相当于 mysql 的  inner join
    pd.merge(df_obj1, df_obj2)
    
    # on显示指定“外键”
    pd.merge(df_obj1, df_obj2, on='key')
    # left_on,right_on分别指定左侧数据和右侧数据的“外键”
    # 更改列名
    df_obj1 = df_obj1.rename(columns={'key':'key1'})
    df_obj2 = df_obj2.rename(columns={'key':'key2'})
    pd.merge(df_obj1, df_obj2, left_on='key1', right_on='key2')
    
    #how指定连接方式
    # “外连接”,outer,j结果中的键是并集
    pd.merge(df_obj1, df_obj2, left_on='key1', right_on='key2', how='outer')
    # 左连接 left
    pd.merge(df_obj1, df_obj2, left_on='key1', right_on='key2', how='left')
    # 右连接 right
    pd.merge(df_obj1, df_obj2, left_on='key1', right_on='key2', how='right')
    
    # 处理重复列名
    df_obj1 = pd.DataFrame({'key': ['b', 'b', 'a', 'c', 'a', 'a', 'b'],
                            'data' : np.random.randint(0,10,7)})
    df_obj2 = pd.DataFrame({'key': ['a', 'b', 'd'],
                            'data' : np.random.randint(0,10,3)})
    
    print(df_obj1)
    print(df_obj2)
    pd.merge(df_obj1, df_obj2, on='key', suffixes=('_left', '_right'))
    
    # 按索引连接
    df_obj1 = pd.DataFrame({'key': ['b', 'b', 'a', 'c', 'a', 'a', 'b'],
                            'data1' : np.random.randint(0,10,7)})
    df_obj2 = pd.DataFrame({'data2' : np.random.randint(0,10,3)}, index=['a', 'b', 'd'])
    print(df_obj1)
    print(df_obj2)
    pd.merge(df_obj1, df_obj2, left_on='key', right_index=True)
    

    数据合并 concat

    沿轴方向将多个对象合并到一起

    import numpy as np
    import pandas as pd
    #NumPy的concat,np.concatenate
    arr1 = np.random.randint(0, 10, (3, 4))
    arr2 = np.random.randint(0, 10, (3, 4))
    
    np.concatenate([arr1, arr2])
    np.concatenate([arr1, arr2], axis=1)
    
    #Series上的concat
    # index 没有重复的情况
    ser_obj1 = pd.Series(np.random.randint(0, 10, 5), index=range(0,5))
    ser_obj2 = pd.Series(np.random.randint(0, 10, 4), index=range(5,9))
    ser_obj3 = pd.Series(np.random.randint(0, 10, 3), index=range(9,12))
    
    pd.concat([ser_obj1, ser_obj2, ser_obj3]) #默认axis = 0
    pd.concat([ser_obj1, ser_obj2, ser_obj3], axis=1)
    
    # index 有重复的情况
    ser_obj1 = pd.Series(np.random.randint(0, 10, 5), index=range(5))
    ser_obj2 = pd.Series(np.random.randint(0, 10, 4), index=range(4))
    ser_obj3 = pd.Series(np.random.randint(0, 10, 3), index=range(3))
    pd.concat([ser_obj1, ser_obj2, ser_obj3])
    
    #join指定合并方式,默认为ourter
    pd.concat([ser_obj1, ser_obj2, ser_obj3], axis=1, join='inner')
    
    #DataFrame上的concat
    df_obj1 = pd.DataFrame(np.random.randint(0, 10, (3, 2)), index=['a', 'b', 'c'],
                           columns=['A', 'B'])
    df_obj2 = pd.DataFrame(np.random.randint(0, 10, (2, 2)), index=['a', 'b'],
                           columns=['C', 'D'])
    
    pd.concat([df_obj1, df_obj2])
    pd.concat([df_obj1, df_obj2], axis=1)
    

    数据重构stack

    1、将列索引旋转为行索引,完成层级索引
    2、DataFrame -> Series

    import numpy as np
    import pandas as pd
    
    df_obj = pd.DataFrame(np.random.randint(0,10, (5,2)), columns=['data1', 'data2'])
    # stack将列索引旋转为行索引,完成层级索引,DataFrame -> Series
    stacked = df_obj.stack()
    print(stacked)
    
    # 默认操作内层索引
    # unstack将层级索引展开,Series -> DataFrame ,默认操作内层索引,即level =-1
    #stacked.unstack()
    # 通过level指定操作索引的级别
    stacked.unstack(level=0)
    

    数据转换

    import numpy as np
    import pandas as pd
    df_obj = pd.DataFrame({'data1' : ['a'] * 4 + ['b'] * 4,
                           'data2' : np.random.randint(0, 4, 8)})
    
    #重复数据
    df_obj.duplicated()
    #删除重复数据
    df_obj.drop_duplicates()
    #删除指定列重复数据
    df_obj.drop_duplicates('data2')
    
    #map函数
    ser_obj = pd.Series(np.random.randint(0,10,10))
    
    ser_obj.map(lambda x : x ** 2)
    

    相关文章

      网友评论

        本文标题:python数据分析之Pandas数据统计/分组/连接/清洗/重

        本文链接:https://www.haomeiwen.com/subject/odksmftx.html