如何进行缺失值处理
(1)删除含有缺失值的样本
(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不是缺失值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)
缺失值处理实例
什么是数据的离散化
连续属性的离散化就是将连续属性的值域划分为若干个离散的区间,最后用不同的符号或整数值代表落在每个子区间中的属性值。
数据离散化的表示形式称为one-hot编码或者哑变量。
为什么要离散化
连续属性的离散化的目的是为了简化数据结构,数据离散化技术可以用来减少给定连续属性值的个数。离散化方法经常作为数据挖掘的工具。
如何实现数据的离散化
(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
按方向拼接
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表示按索引拼接
# 准备数据 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)交叉表与透视表什么作用
找到/探索两个变量之间的关系。
使用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可堆叠,将两个柱子叠加显示使用pivot_table(透视表)实现
# 调用透视表API stock.pivot_table(['pona'], index=['week']) # stock为加了pona和week两列的数据什么是分组与聚合
分组:按照某一个索引分组时,将该索引值相同的分成一组
聚合:数据分组后,一般求出每组最大值作为该组代表保留,即为聚合
分组与聚合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() # 聚合分组与聚合实例 - 星巴克零售店铺数据案例
# 准备数据 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()准备数据
# 准备数据 movie = pd.read_csv('C:/Users/ABC/Desktop/IMDB-Movie-Data.csv') movie.head()问题1:我们想知道这些电影数据中评分的平均分,导演的人数等信息,我们应该怎么获取?
# 评分的平均分 print('-------------Rating_Mean-------------') print( movie['Rating'].mean() ) # 导演的人数 print('-------------Director_Num-------------') print( np.unique(movie['Director']).size ) # 不同电影导演可能相同,所以先去重,np.unique返回ndarray,有size属性问题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()问题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"冷色调