数据分析入门-第四天

数据分析入门

第四天 参考视频

五、Pandas使用 - 高级篇

(一)缺失值处理
  1. 如何进行缺失值处理

    (1)删除含有缺失值的样本

    (2)替换/插补

  2. 如何处理nan

    (1)判断数据中是否存在NaN

    movies = pd.read_csv('C:/Users/ABC/Desktop/IMDB-Movie-Data.csv')
    
    # pd.notnull(movies) # 与下面一句相反,不是缺失值的元素,在其位置显示True;否则显示False
    pd.isnull(movies) # 是缺失值的元素,在其位置显示True;否则显示False
    
    # np.all(pd.notnull(movies)) # 如果有一个False则显示False,表明有缺失值
    np.any(pd.isnull(movies)) # 如果有一个True则显示True,表明有缺失值
    
    # pd.notnull(movies).all() # 为False的字段表示有缺失值
    pd.isnull(movies).any() # 为True的字段表示有缺失值
    '''
    Rank                  False
    Title                 False
    Genre                 False
    Description           False
    Director              False
    Actors                False
    Year                  False
    Runtime (Minutes)     False
    Rating                False
    Votes                 False
    Revenue (Millions)     True
    Metascore              True
    dtype: bool
    '''
    

    (2)删除含有缺失值的样本

    movies.dropna() # axis=0,inplace=False(为True在原有数据修改),返回一个删除Nan项(一行)的DataFrame,不修改原DataFrame
    pd.notnull(movies.dropna()).all() # 全True
    

    (3)替换/插补含有缺失值的样本

    # 1.替换哪些列数据
    # Revenue (Millions)    False
    # Metascore             False
    # 2.用什么值替换 - 此处用平均值
    movies['Revenue (Millions)'].fillna(movies['Revenue (Millions)'].mean(),inplace=True)
    movies['Metascore'].fillna(movies['Metascore'].mean(),inplace=True) # inplace为True在原有数据修改
    pd.notnull(movies).all() # 全True
    
  3. 不是缺失值nan,有默认标记的

    (1)替换 ?-> np.nan

    # 读取数据
    path = "https://archive.ics.uci.edu/ml/machine-learning-databases/breast-cancer-wisconsin/breast-cancer-wisconsin.data"
    name = ['Sample code number', 'Clump Thickness', 'Uniformity of Cell Size', 'Uniformity of Cell Shape', 'Marginal Adhesion', 'Single Epithelial Cell Size', 'Bare Nuclei', 'Bland Chromatin', 'Normal Nucleoli', 'Mitoses', 'Class']
    data = pd.read_csv(path, names=name)
    
    # 替换?->np.nan
    data_new = data.replace( to_replace='?', value=np.nan)
    
    # 处理np.nan缺失值
    data_new.dropna(inplace=True)
    pd.notnull(data_new).all()  # 全True
    

    (2)处理np.nan缺失值的步骤,见2的(2)、(3)

  4. 缺失值处理实例

(二)数据离散化
  1. 什么是数据的离散化

    连续属性的离散化就是将连续属性的值域划分为若干个离散的区间,最后用不同的符号或整数值代表落在每个子区间中的属性值。

    数据离散化的表示形式称为one-hot编码或者哑变量。

  2. 为什么要离散化

    连续属性的离散化的目的是为了简化数据结构,数据离散化技术可以用来减少给定连续属性值的个数。离散化方法经常作为数据挖掘的工具。

  3. 如何实现数据的离散化

    (1)分组

    # 准备数据
    data = pd.Series([165,174,160,180,159,163,192,184],index=["No1:165","No2:174","No3:160","No4:180","No5:159","No6:163","No7:192","No8:184"])
    data
    
    # 1.自动分组 sr=pd.qcut(data, bins) # bins表示分成几组,返回一个series变量
    sr = pd.qcut(data,3)
    # 统计每个区间有多少人
    sr.value_counts()
    
    # 2.转换成one-hot编码
    pd.get_dummies(sr, prefix='height') # prefix给每个分组加的前缀
    
    
    # A.自定义分组 sr=pd.cut(data, []) # []想要分组的边界值组成的列表
    myBins = [150,165,180,195] # 想要分组的边界值 (150,165] (165,180] (180,195]
    sr = pd.cut(data, bins=myBins) # 这样写也可以sr = pd.cut(data, myBins)
    sr.value_counts()
    
    # B.转换成one-hot编码
    pd.get_dummies(sr, prefix='height') # prefix给每个分组加的前缀
    

    (2)将分组好的结果转换成one-hot编码/哑变量,见上面的2和B

(三)合并
  1. 按方向拼接

    pd.concat([a, b], axis=1) # axis=1,将a、b水平拼接,列合并
    
    pd.concat([a, b], axis=0) # axis=0,将a、b竖直拼接,行合并,索引不一致时,将a、b的索引合并,原a/b中没有的项用Nan表示
    
  2. 按索引拼接

    # 准备数据
    left=pd.DataFrame({'key1':['K0','K0','K1','K2'],
    'key2':['K0','K1','K0','K1'],
    'A':['A0','A1','A2','A3'],
    'B':['B0','B1','B2','B3']})
    print('--------left--------')
    print(left)
    
    
    right=pd.DataFrame({'key1':['K0','K1','K1','K2'], 
                        'key2':['K0','K0','K0','K0'], 
                        'C':['Co','C1','C2','C3'],
                        'D':['DO','D1','D2','D3']})
    print('--------right--------')
    print(right)
    
    # inner ,默认内连接
    # inner 保留共有的key
    result_inner = pd.merge(left, right, on=['key1','key2'], how='inner')
    print('-------------inner-------------')
    print(result_inner)
    
    # left ,左连接
    # 左表中所有的key都保留,以左表为主进行合并
    result_left = pd.merge(left,right,on=['key1','key2'],how="left")
    print('-------------left-------------')
    print(result_left)
    
    # right ,右连接
    # 右表中所有的key都保留,以右表为主进行合并
    result_right = pd.merge(left,right,on=['key1','key2'],how="right")
    print('-------------right-------------')
    print(result_right)
    
    # outer ,外连接
    # 左右两表中所有的key都保留,进行合并
    result_outer = pd.merge(left,right,on=['key1','key2'],how="outer")
    print('-------------outer-------------')
    print(result_outer)
    
(四)交叉表与透视表
  1. 交叉表与透视表什么作用

    找到/探索两个变量之间的关系。

  2. 使用crosstab(交叉表)实现

    # 准备数据
    stock = pd.read_csv('C:/Users/ABC/Desktop/stock_day.csv')
    
    # 准备日期数据
    stock.index # 行索引,日期
    date = pd.to_datetime(stock.index)
    date.weekday # 行索引日期转化为星期几
    stock['week'] = date.weekday
    stock # 添加week列到stock_primary中
    
    # 准备涨跌幅数据
    stock['pona'] = np.where(stock['p_change']>0, 1, 0) # stock['p_change']>0的为1,否则为0
    
    stock
    
    # 调用交叉表API
    stock_cross = pd.crosstab(stock['week'], stock['pona'])
    stock_cross_sum = stock_cross.sum(axis=1) # axis=1,按列求和 将所得到的pona为0和1的两列求和,用于求频率
    stock_cross_process = stock_cross.div(stock_cross_sum,axis=0) # axis=0按行做除法
    stock_cross_process.plot(kind='bar',stacked=True) # stacked可堆叠,将两个柱子叠加显示
    
  3. 使用pivot_table(透视表)实现

    # 调用透视表API
    stock.pivot_table(['pona'], index=['week']) # stock为加了pona和week两列的数据
    
(五)分组与聚合
  1. 什么是分组与聚合

    分组:按照某一个索引分组时,将该索引值相同的分成一组

    聚合:数据分组后,一般求出每组最大值作为该组代表保留,即为聚合

  2. 分组与聚合API

    # 准备数据
    col = pd.DataFrame({'color':['white','red','green','red','green'],
                       'object':["pen","pencil","pencil","ashtray","pen"],
                      'price1':[4.56,4.20,1.30,0.56,2.75],
                      'price2':[4.75,4.12,1.68,0.75,3.15]})
    col
    
    # 进行分组,对颜色进行分组,对价格price1进行聚合
    
    # 用DataFrame的方法进行分组聚合
    col.groupby(by="color")["price1"].max() # 分组后并不会直接出结果,所以又对price1聚合
    
    # 用Series的方法进行分组
    col['price1'].groupby(col["color"]) # 先找到price1的series,然后根据color的series分组,同样分组后并不会直接出结果
    col['price1'].groupby(col["color"]).max() # 聚合
    
  3. 分组与聚合实例 - 星巴克零售店铺数据案例

    # 准备数据
    starbucks = pd.read_csv('C:/Users/ABC/Desktop/directory.csv')
    starbucks.head()
    
    # 按国家分组,求出每个国家星巴克店铺数量
    starbucks.groupby(by='Country').count()
    
    # 分组后,每一列其实都可以代表店铺数量,此处就取brand列
    # 对分组后数据降序排序,取前十个画出柱状图
    starbucks.groupby(by='Country').count()['Brand'].sort_values(ascending=False)[:10].plot(kind='bar', figsize=(20,8), fontsize=20)
    
    # 先按国家分组,再按省市分组
    starbucks.groupby(by=['Country','State/Province']).count()
    
(六)综合案例
  1. 准备数据

    # 准备数据
    movie = pd.read_csv('C:/Users/ABC/Desktop/IMDB-Movie-Data.csv')
    movie.head()
    
  2. 问题1:我们想知道这些电影数据中评分的平均分,导演的人数等信息,我们应该怎么获取?

    # 评分的平均分
    print('-------------Rating_Mean-------------')
    print( movie['Rating'].mean() )
    
    # 导演的人数
    print('-------------Director_Num-------------')
    print( np.unique(movie['Director']).size ) # 不同电影导演可能相同,所以先去重,np.unique返回ndarray,有size属性
    
  3. 问题2:对于这一组电影数据,如果我们先rating,runtime的分布情况,应该如何呈现数据?

    # 问题2:对于这一组电影数据,如果我们先rating,runtime的分布情况,应该如何呈现数据?
    
    # 1.创建画布
    plt.figure(figsize=(20,8), dpi=80)
    
    # 2,绘制直方图
    plt.hist(movie['Rating'], 20)
    # 修改刻度
    plt.xticks(np.linspace(movie['Rating'].min(), movie['Rating'].max(), 21)) # linspace左闭右闭,21个点分20段
    # 添加网格
    plt.grid(linestyle='--', alpha=0.5)
    
    # 3.显示图像
    plt.show()
    
  4. 问题3:对于这一组电影数据,如果我们希望统计电影分类(genre)的情况,应该如何处理数据?

    # 问题3:对于这一组电影数据,如果我们希望统计电影分类(genre)的情况,应该如何处理数据?
    
    # 先统计电影类别有哪些
    movie_genre_first = [i for i in movie['Genre']]
    movie_genre_first # 数据样式['Action,Adventure,Sci-Fi','Adventure,Mystery,Sci-Fi','Horror,Thriller']
    
    movie_genre_second = [i.split(',') for i in movie['Genre']]
    movie_genre_second # 数据样式[['Action', 'Adventure', 'Sci-Fi'],['Adventure', 'Mystery', 'Sci-Fi'],['Horror', 'Thriller']]
    
    movie_genre_third = [j for i in movie_genre_second for j in i]
    movie_genre_third #数据样式['Action','Adventure','Sci-Fi','Adventure','Mystery','Sci-Fi','Horror','Thriller']
    
    movie_class = np.unique(movie_genre_third)
    movie_class
    
    # 统计每个类别有几个电影
    
    # 先建立一个1000*20的空表(总共1000部电影,20个分类)
    count = pd.DataFrame(np.zeros(shape=(1000,20), dtype='int32'), columns=movie_class)
    
    movie_genre_second
    movie_genre_second[0] # Results:['Action', 'Adventure', 'Sci-Fi']
    
    # 计数填表
    for i in range(1000):
        count.loc[i,movie_genre_second[i]] = 1 # i=0时count.loc[0,['Action', 'Adventure', 'Sci-Fi']],索引到第0行这三列对应的三个元素,都赋值为1
    count # 此时count每一行,有该电影分类时元素值为1
    
    count.sum(axis=0)  # 按列求和,即得电影每个分类数量
    
    count.sum(axis=0).sort_values(ascending=False).plot(kind='bar', fontsize=20, figsize=(20,9), colormap="cool") # colormap="cool"冷色调
    
©️2020 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页