美文网首页数据分析学习笔记
Python数据分析案例总结 2020.3.12

Python数据分析案例总结 2020.3.12

作者: 虎嗅蔷薇_c244 | 来源:发表于2020-03-12 00:47 被阅读0次

    近期做了四个Python数据分析的案例实践,把流程、语句和想法归纳总结,做一个小小的里程碑

    1.流程

    明确分析目的->由数据源构建指标体系->数据清洗->数据处理及分析->结论

    2.明确分析目的

    -->分析问题产生的原因/分析业务现状/通过分析对业务进行指导……
    目的——是具体的、充满定语的、具有返回值的

    3.由数据源构建指标体系

    区分维度和指标:
    维度:对应数据的每一列,多个列组合也可以认为是一个维度
    指标:各种统计值
    在不同维度上得到各种指标
    根据不同数据源和分析目的搭建指标体系
    eg:一款付费软件的日活/人均付费/付费渠道/付费功能/使用频次/使用时长……

    4.数据清洗

    4.1导入库

    import numpy as np
    import pandas as pd
    import matplotlib.pyplot as plt
    

    4.2加载文件

    df = pd.read_csv('./file.csv')
    

    4.3简单查看数据有哪些列&类型

    df.info() # 可看到缺失行在某一列上的条目数少于总数,但当列数目较多时,不容易发现
    df.head()
    

    4.4查看数据的整体信息

    df.describe()  # 整数型或浮点型数据
    df.count() # 查看各列非空数据量
    

    4.5开始数据清理

    ->对需要分析的维度进行清理
    ->对于数值型数据,可以通过describe方法输出信息,关注最大值、最小值、平均值、行数等是否符合常理或是否满足本次数据分析目的对数据的要求

    4.5.1判断数据是否有null值、0值等

    若null值所在行数较少,删除后不会对总体数据产生较大影响

    df[df.salary.isnull()] 输出salary列null值所在行的全部信息
    df.drop(df[df.salary.isnull()].index, inplace = True)
    df[df.salary.isnull()] # 查看是否删除成功
    

    若不想删除数据,则可用聚合函数或前值/后值等替换处理,如使用平均数替换

    df['salary'].replace(0,df['salary'].mean(), inplace = True)
    # 注:若遇到较多0值,且要采用平均数填充,可先将0值替换为np.nan,再使用列名.fillna()填充该列数据平均数,这样在计算平均数时nan所在行不会对整体平均数产生影响(不计入在内)
    df.salary.replace(0,np.nan, inplace = True)
    df.salary.fillna(df['salary'].mean(), inplace=Ture)
    df['communityAverage'].fillna(df['communityAverage'].mean(), inplace=True) # 对null值,也可使用fillna
    

    df.info() 查看是否有Nan值
    Nan非null值,无法用 .isnull()判断
    但通过df.info()判断存在缺失值,但又不是null时,可查看其是否为Nan值

    df['Type'].value_counts(dropna = False) #统计包括Nan在内的数据
    data.dropna()  # 默认axis=0,how='any',删除带有空值的行,只要有一个空值,就删除整行
    df.dropna(how='all')            # 整行都是空值时,才会被删除
    df.dropna(how='all',axis=1))    # 整列都是空值时,才会被删除
    df.dropna(subset=[1,2])         # 删除指定1和2列中包含缺失值的行
    

    4.5.2 查看是否具有重复值,展示重复的条目

    如果有重复值,⼀般最后处理,因为其他的列可能会影响到删除那⼀条重复的记录
    先处理其他的列

    df[df.duplicated()]  #注意这样使用是展示各字段完全相同的条目
    df.drop_duplicates('App', inplace = True)# 删除'App'列中数据重复的行
    

    也可根据指定部分列(待分析列)是否具有重复值

    df[df[:,['employee_ID','deptno_ID','salary']].dupliacted()]
    df[df.employee_ID.dupliacted()] # 单独查看employee_ID是否具有重复值的条目
    

    或使用行数是否相等来判断

    len(df.empolyee_ID.unique()) 与 len(df) # 是否相等,相等->该列无重复
    df['employee_ID'].value_counts() # 默认剔除nan值 # 是否有大于1的
    df['employee_ID'].value_counts(dropna = False) # 计算包含nan值的条目
    pd.unique(df['employee_ID']).size # 是否与整个数据行数相同
    

    注意:当我们对⼀列取size属性的时候,返回的是⾏数,如果对于dataframe使⽤size,返回的是行乘以列的结果,也就是总的元素数

    4.5.3 删除非所需数据

    df.drop(df[df['hiretime'].dt.year<2015].index, inplace = True)
    df.drop(df[df['hiretime'].dt.year>2019].index, inplace = True)
    df['hiretime'].dt.year.value_counts()
    

    4.5.4 使用分类查看是否有不合逻辑的类型

    df['nationality'].value_counts()
    

    比如该列都是用国家英文全称来填充的,但某个结果中若出现数字-->不合逻辑-->是因为没有把数字标号转换为国家还是因为其他原因?

    4.5.5 判断字符串类型数据是否只由数字组成

    df['deptno_info'].str.isnumeric() --> True or False
    df['deptno_info'].str.isnumeric().sum() -->True 的条目数
    

    数据格式转换

        df['deptno_info'].astype('i8') #将本列转换为数值格式
    

    说明:
    isnumeric() 方法检测字符串是否只由数字组成。这种方法是只针对unicode对象。
    注:定义一个字符串为Unicode,只需要在字符串前添加 'u' 前缀即可,如 str1 = u'Itachi';
    对于 Unicode 数字、全角数字(双字节)、罗马数字和汉字数字会返回 True ,其他会返回 False。byte数字(单字节)无此方法。

    print u'123'.isnumeric() # True
    print u'Ⅷ'.isnumeric() # True
    print u'abc123'.isnumeric() # False
    print u'1.23'.isnumeric() # False
    

    4.5.6 单位转化 str.replace()

    eg:数据单位的简化处理
    tips:转化为数据较小单位时可以实现-->转化后数据成为整数int类型,而非float

    df['size'] = df['size'].replace('M','e+6') #M-->10^6 
    df['size'] = df['size'].replace('k','e+3') #k-->10^3
    df['size'] = df['size'].replace(',','') # 替换千位符
    df['Size'].astype('f8')
    

    使用is_convertable(v)函数定义一个方法,判断字符串判断是否可以转换

    def is_convertable(v): 
        try:
            float(v)
            return True
        except ValueError:
            return False
    

    查看不能转换的字符串分布

    temp = df['size'].apply(is_convertable) -->能转换 True
    df['size'][-temp].value_counts() --> -temp 取False的
    # 转换剩下的字符串
    df['size'] = df['size'].str.replace('Varies with device','0')
    # 再看下是不是还有没转换的字符串
    temp = df['size'].apply(is_convertable)
    df['size'][-temp].value_counts()
    # 转换类型
    # e+5这种格式使⽤astype直接转为int有问题,如果想转成int,可以先转成f8,再转i8
    #df['size'] = df['size'].astype('f8').astype('i8')
    df['size'] = df['size'].astype('i8')
    # 将size为0的填充为平均数
    df['size'].replace(0,df['size'].mean(), inplace = True)
    df.describe()
    

    5.数据分析

    5.1样本总数

    df.count()
    

    5.2数值类型列的常见统计指标

    df.describe()
    

    5.3采用不同维度和指标进行分析

    ① 分组 groupby
    分组统计不同国家人员并保留两列

    nationality_data = df.groupby('nationality',as_index = False).count()[['nationality', 'ID']]
    nationality_data.rename(columns={'ID':'employee_count'},inplace = True) #重命名ID列-->上述操作后ID列实际为总数
    

    不同部门中雇员平均工资

    deptno_data = df.groupby('deptno',as_index = False).mean()[['deptno','salary']
    

    对不同分组下另一维度进行排序
    eg:对App分类分组后计算其他维度平均值,并按照平均安装量对各组降序排列

    df.groupby('category').mean().sort_values('installs', ascending = False)
    

    多列分组

    # type --> free or charges
    # category --> family or media or chat ..........
    df.groupby(['type','category'].mean().sort_values('reviews', ascending = True/False, inplace = True/False)
    

    ② 分类计数

    groupby().count()
    df.groupby('nationality').count()
    value_counts() 
    

    eg:统计每年入职人数
    年份跨度较大时,有些年份可能数据较少;年初或年中时,当年数据可能较少
    看下每年数据的数量,确定是否要删除数据少的年份
    将字符串转化为日期格式,方便使用内置函数

    df['hiretime'] = pd.to_datetime(df['hiretime'])
    df['hiretime'].dt.year.value_counts()
    

    分类计算比例
    eg:对类型和分类分组后,对其评论安装比进行排序

    g = df.groupby(['type','category']).mean()
    (g['reviews'] / g['installs']).sort_values(ascending = False)
    

    ③ 按照数值排序 sort_values()

    nationality_sorted_data = nationality_data.sort_values('employee_count', ascending=False)
    nationality_sorted_data[nationality_sorted_data.employee_count>100] # 显示employee_count数量大于100的数据列表
    df.sort_index(inplace = True) # 按照索引排序 sort_index() 
    

    ④ 分桶 pd.cut-groupby
    雇员年龄分布
    生成桶,5岁一个分桶 最小18岁,最大60岁

    bins = np.arange(18,63,5)
    bins_data = pd.cut(df['age'],bins)
    bin_counts = df['age'].groupby(bins_data).count()
    # 为图表展示好看使用列表生成式处理index
    bin_counts.index = [str(x.left) + '-' + str(x.right) for x in bin_counts.index]
    

    ⑤ 单独取出某列
    eg:取出2017年,国籍为China的所有数据

    df_2017 = df[df['hiretime'].dt.year == 2017]
    df_2017_China = df_2017[df_2017['nationality'] == 'China']
    df_2017_China.describe()
    

    ⑥ 占比 len()/len()
    统计salary在50~100之间的数据在所有数据中的占比

    len(df[df['salary'] > 50]) & len(df[df['salary'] < 100])/len(df)
    

    ⑦ 相关性(0.5以上可以认为相关,0.3以上可以认为是弱相关)

    df.corr() # 列出二维相关性表
    

    ⑧ .head() .tail()

    # 取某维度的前十名和后十名
    print(product_orderby_count.head(10))
    print(product_orderby_count.tail(10))
    

    ⑨ .intersection() 交集
    看下销售额和销量最后100个的交集,如果销售额和销量都不行,这些商品需要看看是不是要优化或者下架

    problem_productids = productid_turnover.tail(100).intersection(product_orderby_count.tail(100).index)
    

    5.4 matplotlib查看数据效果

    bin_counts.plot()
    plt.show()
    

    注意点:
    1.drop、rename等方法具有inplace参数,具体见帮助文档,学习初期往往忽略此参数,导致数据未在原表上修改或未设置接收变量。运行后无输出则说明inplace为TRUE(jupyter notebook的使用优点),若有输出则应赋予接收变量或为inplace赋值;而replace没有inplace参数,需要设置接收值
    2.对多列进行操作时,留心是否需要多加一层括号,如 df.groupby(['district', 'elevator'])
    3.注意到df_dis_want[(df['year'] == '2017')]判别条件这里,数据类型不同判别条件中需要考虑是否加引号'',或者可认为是数据清洗环节的疏漏

    相关文章

      网友评论

        本文标题:Python数据分析案例总结 2020.3.12

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