jzlixiao 2020-05-09
数据处理基本就是使用pandas, pandas就是numpy++
pandas是一个强大的数据分析工具集
1. numpy能够帮我们处理数值型数据,但是这还不够,很多时候我们除了数值之外,还有字符串,时间序列等 (1) 我们通过俺从获取到了存储在数据库中的数据 (2) youtube的例子中除了数值之外还有国家的信息,视频的分类信息,标题信息等 2. numpy可以帮助我们处理数值,但是pandas除了处理数值(基于numpy),还能帮我处理其他类型的数据
(1) Series (2) Dataframe
1. 要想学好Pandas,前提是要对pandas的数据结构有所了解. 2. pandas中有两个主要的数据结构: Series和DataFrame (1) Series是一维的数据结构(带标签(索引)的数组) (2) DataFrame是二维的数据结构(Series容器)
Series是一种类似于一维数组的对象,由一组数据(各种numpy的数据类型)以及一组与之对应的索引(数据标签)组成 (1) 类似一维数组的对象 (2) 由数据和索引组成 1) 索引(index)在左,数据(values)在右 2) 索引是自动创建的
Series创建
1. Pandas的Series类对的构造方法: class pandas.Series(data=None,index=None,dtype=None,copy=False,...) (1) data: 传入的数据,可以是ndarray,list等序列,还可以通过字典来创建 (2) index: 索引序列,必须是唯一的,且与数据的长度相同. 如果没有传入索引参数,则默认会自动创建一个从0~N的整数索引 (3) dtype: 数据类型 (4) copy: 是否复制数据,默认为False
通过序列来创建Series对象
# code01_通过序列创建Series.py import pandas as pd # pd.Series()的构造方法如下 # _init__(self, data: Any = None, index: Any = None, dtype: Any = None, name: Any = None, copy: Any = False, fastpath: bool = False) -> Any ser_obj01 = pd.Series([1, 2, 3, 4, 5, 6]) # 通过列表创建Series对象 print(ser_obj01) print(‘-‘ * 30) ser_obj02 = pd.Series(range(1, 7), [x for x in "abcdef"]) # 按索引(标签)也给指定了 print(ser_obj02)
通过字典来创建Series对象
# code02_通过字典创建Series.py import pandas as pd # 字典创建Series, key就是索引, value就是value => 刚好一一对应 temp_dic = dict(name="张三", age=23, job="程序员") ser_obj01 = pd.Series(temp_dic) print(ser_obj01)
属性 index 和 values
index 是 Index类的一个对象
values是ndarray
# code03_属性index和values.py import pandas as pd # 字典创建Series, key就是索引, value就是value => 刚好一一对应 temp_dic = dict(name="张三", age=23, job="程序员") ser_obj01 = pd.Series(temp_dic) # 获得 index 和 values两个属性 ser_index = ser_obj01.index ser_values = ser_obj01.values print(type(ser_index)) # <class ‘pandas.core.indexes.base.Index‘> print(ser_index) # 输出index属性 print(type(ser_values)) # <class ‘numpy.ndarray‘> print(ser_values) # 输出values属性 print(‘-‘ * 30) # 可以直接通过索引值来获取属性 print("ser_obj01[\"name\"]:", ser_obj01["name"]) print("ser_obj01[\"age\"]:", ser_obj01["age"]) print("ser_obj01[\"job\"]:", ser_obj01["job"]) # 即使Series进行了运算,运算后的values依然和index一一对应 print(‘-‘ * 30) print(ser_obj01 * 3) # 让每个values都*3
1. DataFrame是一个表格型的数据结构,它含有一组有序的列,每列可以是不同类型的值. 2. DataFrame既有行索引也有列索引,它可以被看做是由Series组成的字典(共用一个索引),数据是以二维结构存放的. (1) 类似多维数组/表格数据(如 excel,R中的data.frame) (2) 同一列数据必须是相同的类型(相当于一竖列就是一个Series) (3) 索引包括列索引和行索引 3. Pandas的DataFrame类对象的构造方法: pands.DataFrame(data=None,index=Noen,columns=None,dtype=None,copy=False) (1) index: 行标签,如果没有传入索引参数,则默认创建一个从0~N的整数索引 => 0轴,axis=0 (2) columns: 列标签,如果没有传入索引参数,则默认创建一个0~N的整数索引 => 1轴,axis=1 (3) data: 这里传入的data是二维的序列
通过二维序列创建DataFrame
# code05_通过二维序列创建DataFrame.py import numpy as np import pandas as pd a = np.random.randn(5, 4) # 创建一个5行4列的标准正态分布数组 print(a) print(‘-‘ * 30) # pd.DataFrame() # __init__(self, data=None, index=None, columns=None, dtype=None, copy=False) # 1. 通过二维ndarray创建DataFrame对象 df_obj01 = pd.DataFrame(a) # 传入二维的ndarray print(df_obj01) print(‘-‘ * 30) # 2. 其实通过二维序列也是一样的道理 # 这里同时传入行索引和列索引 index = list("abcde") columns = ["No{}".format(i) for i in range(1, 5)] b = np.arange(20).reshape(5, 4) df_obj02 = pd.DataFrame(b, index=index, columns=columns) # 传入二维的ndarray print(df_obj02) print(‘-‘ * 30)
通过字典创建DataFrame
# code06_通过字典创建DataFrame.py import numpy as np import pandas as pd d1 = dict(name=["张三", "李四", "王五", "赵六"], age=[23, 24, 25, 26], score=[93, 94, 95, 96]) df_obj01 = pd.DataFrame(d1) # 传入了字典,其实也就相当于指定指定了columns print(df_obj01)
通过列索引获取列数据(Series类型)
(1) df_obj.列索引的名称 (2) df_obj[列索引的名称]
一般推荐使用后者,使用索引的方式而不是使用属性的方式来获取列数据
# code07_DataFrame通过列索引获得列数据.py import numpy as np import pandas as pd # 一列数据就是一个Series (1) 列索引位置 (2) 列索引名称 d1 = dict(name=["张三", "李四", "王五", "赵六"], age=[23, 24, 25, 26], score=[93, 94, 95, 96]) df_obj01 = pd.DataFrame(d1) # 传入了字典,其实也就相当于指定指定了columns element01 = df_obj01["name"] # 通过列索引名称获得一列数据 print(element01) print(type(element01)) # <class ‘pandas.core.series.Series‘> print(‘-‘ * 30) element02 = df_obj01.name # 通过列索引这个属性获得一列数据 print(element02) print(type(element02)) # <class ‘pandas.core.series.Series‘>
增加列数据和删除列数据
增加一列相当于增加了一个字段
1. DataFrame增加列数据类似于Python给字典添加一个键值对,如: df_obj[‘No4‘]=[‘g‘,‘h‘] 2. DataFrame删除一列列数据,使用del关键字实现,如: del df_obj[‘No3‘]
# code08_DataFrame增加列和删除列.py import numpy as np import pandas as pd d1 = dict(name=["张三", "李四", "王五", "赵六"], age=[23, 24, 25, 26], score=[96, 95, 94, 93]) df01 = pd.DataFrame(d1) print(df01) print(‘-‘ * 30) # 1. 给DataFrame增加列,操作和Python给字典增加新的键值对一致 df01[‘gender‘] = [‘男‘, ‘男‘, ‘女‘, ‘女‘] # 增加一列属性 df01[‘school‘] = [‘广西大学‘, ‘广东工业大学‘, ‘广西师范大学‘, ‘广东财经大学‘] print(df01) print(‘-‘ * 30) # 2. 删除DataFrame中的列, 使用del关键字 del df[‘列索引名称‘] del df01[‘gender‘] # 删除性别属性 print(df01) print(‘-‘ * 30)
DataFrame基本使用
1. DataFrame的基础属性 (1) df.shape # 行数 列数 (2) df.dtypes # 列数据类型 (注意,是dtypes不是dtype) (3) df.ndim # 数据维度 (4) df.index # 行索引 (5) df.columns # 列索引 (6) df.values # 对象值,二维ndarray数组 2. DataFrame整体情况查询 (1) df.head(3) # 显示头部几行,默认5行 (2) df.tail(3) # 显示末尾几行,默认5行 (3) df.info() # 相关信息查看: 行数,列数,列非空值个数,列类型,内存占用 (4) df.describe() # 快速综合统计结果: 计数,均值,标准差,最大值,四分位数,最小值
# code09_DataFrame基本使用.py import numpy as np import pandas as pd d1 = dict(name=["张三", "李四", "王五", "赵六"], age=[23, 24, 25, 26], score=[93, 94, 95, 96]) df = pd.DataFrame(d1) # DataFrame的基本属性 # (1) df.shape print("df.shape: ", df.shape) print(‘-‘ * 30) # (2) df.dtypes print("df.dtypes: ", df.dtypes) print(‘-‘ * 30) # (3) df.ndmin print("df.ndim: ", df.ndim) print(‘-‘ * 30) # (4) df.index print("df.index: ", df.index) print(‘-‘ * 30) # (5) df.columns print("df.columns: ", df.columns) print(‘-‘ * 30) # (6) df.values print("df.values: ", df.values) print(‘-‘ * 30) # 2. DataFrame整体情况查询 # (1) df.head() 显示头部几行,默认前5行 print("df.head(2):", df.head(2)) print(‘-‘ * 30) # (2) df.tail() 显示头部几行,默认前5行 print("df.tail(2):", df.tail(2)) print(‘-‘ * 30) # (3) df.info() 查看信息 print("df.info():", df.info()) print(‘-‘ * 30) # (4) df.describe() 快速综合统计结果 print("df.describe():", df.describe()) print(‘-‘ * 30)
# code10_统计狗的名字使用情况.py import numpy as np import pandas as pd # pd.read_csv() => 读出csv文件并转换为df对象 df = pd.read_csv(r"./dogNames.csv") # print(df) # print(df.info()) => df.info() 快速查看一下统计信息 # DataFrame中的排序方法 # pd.DataFrame.sort_values(by=[‘列索引名称1‘,‘列索引名称2‘,...]) DataFrame要指定排序的列索引 df = df.sort_values(by=["Count_AnimalName"],ascending=False) print(df) print(‘-‘ * 30) # 查看前10个大的 print(type(df.tail(10))) # <class ‘pandas.core.frame.DataFrame‘> print(df.head(10)) # 查看前10个最大的
索引对象
1. Pandas中的索引都是Index类对象,又称索引对象,该对象是不可以进行修改的,以保证数据安全. (1) 如果修改索引值会报错 => ser.index[‘a‘] = 2 # 这个是错的,索引不能修改 2. Index类的不可变性是非常重要的,正因为如此,多个数据结构之间才能够安全的共享Index类对象 ser01 = pd.Series(range(3),index=[a,b,c]) ser02 = pd.Series(range(8),index=ser01.index) # ser02可以直接使用ser01的索引 print(ser01.index is ser02.index) 3. Index类对象是可迭代的,可实现的很多操作: (1) for x in ser.index: # 迭代遍历 (2) type(ser.index) # 查看类型 (3) list(ser.index) # 转换为 list (4) len(ser.index) # 获取长度
Series索引
1. Series有关索引的用法类似于Numpy数组中索引,只不过Series的索引不只是整数.如果要获取某个数据的值,可以 (1) 索引的位置来获取值 (2) 索引的名称来获取值 2. Series的切片操作 (1) 索引的位置来切片 [) => ser_obj[2:4] (2) 索引的名称来切片 [] => ser_obj[‘c‘:‘e‘] 3. Series不连续索引 不连续只要传入这个不连续索引的值的序列即可 ser_obj[[不连续索引序列]] (1) 索引的位置 ser_obj[[0,2,4]] (2) 索引的名称 ser_obj[[‘a‘,‘c‘,‘d‘]] 4. 布尔型索引 使用布尔型也是进行布尔运算,然后会的返回的新的布尔数组 ser_bool = ser_obj>2 # 获得布尔数组 ser_obj[ser_bool] # 获得结果为True的数据
# code04_Series的索引操作.py import pandas as pd ser_obj = pd.Series(range(1, 6), [chr(ord(‘a‘) + x) for x in range(5)]) print(ser_obj) print(‘-‘ * 30) # 1. 使用索引获得值 (1)索引位置 (2) 索引名称 print("ser_obj[2]:", ser_obj[2]) # 使用索引位置获取值 print("ser_obj[‘c‘]:", ser_obj[‘c‘]) # 使用索引名称获取值 print(‘-‘ * 30) # 2. Series切片 print("ser_obj[2:4]:\n", ser_obj[2:4]) # 通过索引位置切片 [) print("ser_obj[‘c‘:‘e‘]:\n", ser_obj[‘c‘:‘e‘]) # 通过索引名称切片 [] print(‘-‘ * 30) # 3. Series不连续索引 print("ser_obj[[0, 2, 4]]:\n", ser_obj[[0, 2, 4]]) # 通过索引位置 print("ser_obj[[‘a‘, ‘c‘, ‘d‘]]:\n", ser_obj[[‘a‘, ‘c‘, ‘d‘]]) # 通过索引名称 print(‘-‘ * 30) # 4. 布尔索引 ser_bool = ser_obj > 2 # 获得布尔值数组 print(ser_obj[ser_bool]) # 输出大于2的值 # print(ser_obj[ser_obj>2])
DataFrame索引
1. df[ ]--选择列,整数可以选择行,但是不能单独选择,要用切片的方式如df[:2] (1) df[["colums1","columns2",......]] 通过这样来选择列 (2) df[index1:index2] 通过这个才可以对行进行切片 (3) df[["colums1","columns2",......]] 切片的同时是选择行 2. 布尔索引 df[布尔索引] df[(df["Row_Labels"].str.len()>4) & (df["Count_AnimalName"]>700)] (1) 有两个连接符 &,| (2) 两个不同条件之间需要使用() 括起来
# code12_DataFrame索引使用.py import numpy as np import pandas as pd # pd.read_csv() => 读出csv文件并转换为df对象 df = pd.read_csv(r"./dogNames.csv") print(df.info()) print(‘-‘ * 30) # 1. df[ ]--选择列,整数可以选择行,但是不能单独选择,要用切片的方式如df[:2] # (1) df[["colums1","columns2",......]] 通过这样来选择列 print(df[["Row_Labels", "Count_AnimalName"]]) # 选择指定的列输出 print(‘-‘ * 30) # (2) df[index1:index2] 通过这个才可以对行进行切片 print(df[:20]) # 输出前20行 (只能切片,不能进行单独的选择) print(‘-‘ * 30) # (3) df[["colums1","columns2",......]] 切片的同时是选择行 print(df[:20]["Row_Labels"]) # 切片同时选择指定的列 print(‘-‘ * 30) # 2. 布尔索引 df[布尔索引] # (1) 连接符 & | (2) 不同条件之间要使用括号括起来 print(df[(df["Row_Labels"].str.len() > 4) & (df["Count_AnimalName"] > 700)]) print(‘-‘ * 30)
高级索引: 标签,位置和混合
(1) loc标签索引 (2) iloc位置索引
使用loc,iloc,那么DataFrame的切片操作就和ndarry的二维数组切片一致
1. 虽然DataFrame操作索引能够满足基本数据查看请求,但是仍然不够灵活. 为此,pandas提供了loc和iloc. 2. loc: 基于标签索引(索引名称),用于按标签选取数据. df.loc[行,列] 3. iloc: 基于标签位置,按位置选取数据 df.iloc[行,列] 4. 注意: (1) 位置的切片是不包含末尾,而标签切片是包含末尾的 (2) 花式索引与ndarray不太一致,ndarray花式索引取出是一个一个值,但是DataFrame取出是一行一行
# code13_loc和iloc.py import numpy as np import pandas as pd # 通过df.loc[行,列] df.iloc[行,列] 实现了DataFrame和numpy二维数组切片操作的一致 arr = np.arange(16).reshape(4, 4) df = pd.DataFrame(arr, columns=list("abcd")) print(df) print(‘-‘ * 30) # 1. 使用df.loc[] 按照索引标签名字 print(df.loc[:, ["c", "a"]]) # 全部行的c,a列 print(‘-‘ * 30) print(df.loc[[0, 2], [‘a‘, ‘c‘]]) # 要注意DataFrame的花式索引与ndarray有点不同 print(‘-‘ * 30) # 2. df.iloc[] 按照索引位置 print(df.iloc[:, [2, 0]]) # 全部行的c,a列 print(‘-‘ * 30) print(df.iloc[[0, 2], [0, 2]]) print(‘-‘ * 30)
apply和applymap
1. 可以直接使用numpy的函数
排序
(1) ser.sort_index() df.sort_index()
(2) ser.sort_values() df.sort_values(by=[])
1. 索引排序 Pandas中按索引排序使用的是sort_index(),该方法可以用行索引或者列索引进行排序 sort_index(axis=0,level=None,ascending=True,inplace=False,kind=‘quicksort‘...) (1) axis: 轴索引(排序的方向),0表示index(按行),1表示columns(按列),默认按index (2) level: 若不为None,则对指定索引级别的值进行排序 (3) ascending: 是否升序排序,默认为True,表示升序 (4) inpalce: 默认为False,表示对数据表进行排序,返回一个新的排序数组 (5) kind: 选择排序算法,默认为quicksort 2. 按值排序 sort_values(by,axis=0,ascending=True,inplace=False,kind=‘quicksort‘,na_position=‘last‘) (1) by: 表示排序的列 (2) na_position: 参数只有两个值 first,last.若为first,则会将NaN值放在开头. 默认NaN值是放在末尾
# code11_pandas数据排序.py import numpy as np import pandas as pd # 1. 按索引排序 # sort_index(axis=0,level=None,ascending=True,inplace=False,kind=‘quicksort‘...) ser = pd.Series(range(10, 15), index=[5, 3, 1, 3, 2]) # 这里索引标签是可以同名的 print(ser) print(‘-‘ * 30) ser.sort_index(inplace=True) # 按索引值升序排序 print(ser) print(‘-‘ * 30) ser.sort_index(ascending=False, inplace=True) # 按索引值降序排序 print(ser) print(‘-‘ * 30) df = pd.DataFrame(np.arange(9).reshape(3, 3), index=[4, 3, 5]) print(df) print(‘-‘ * 30) df = df.sort_index() # 默认按index升序排序,返回一个新的数组 print(df) print(‘-‘ * 30) # 2. 按值排序 # sort_values(by,axis=0,ascending=True,inplace=False,kind=‘quicksort‘,na_position=‘last‘) ser = pd.Series([4, np.nan, 6, np.nan, -3, 2]) print(ser) print(‘-‘ * 30) ser.sort_values(inplace=True) # 默认NaN在最后,升序排序 print(ser) print(‘-‘ * 30) d1 = dict(No1=[0.4, -0.1, -0.3, 0.0], No2=[0.2, 0.6, -0.1, -0.7], No3=[0.8, 0.6, -0.5, 0.1]) df = pd.DataFrame(d1) print(df) print(‘-‘ * 30) df.sort_values(by=["No1","No2","No3"],inplace=True) # 按照关键字 No1 No2 No3 进行排序 print(df) print(‘-‘ * 30)
处理缺失数据
1. 一般空值使用None表示,缺失值使用NaN表示. 2. Pandas中提供了一些用于检查或处理空值(None)和缺失值(NaN)的函数. (1) pd.isnull() / pd.notnull() 判断数据集合中是否存在空值和缺失值 (2) pd.dropna() 和 pd.fillna() 对空值和缺失值进行删除和填充 3. pd.isnull(obj)/pd.notnull(obj) 4. pd.dropna(axis=0,how=‘any‘,thresh=None,subset=None,inplace=False) (1) axis: 确定过滤行或列 1) 0为index,删除包含缺失值的行,默认为0 2) 1为columns,删除包含缺失值的列 (2) how: 确定过滤的标准,取值可以为 1) any: 默认值,如果存在NaN值,则删除该行或该列 2) all: 如果所有值都是NaN值,则删除该行或该列 (3) thresh: 表示有效数据量的最小要求. 若传入了2,则是要求该行或该列至少有两个非NaN值将其保留 (4) subset: 表示在特定的子集中寻找NaN值 (5) inplace: 表示是否在原数据上操作 5. pd.fillna(value=None,method=None,limit=None.....) (1) value: 用于填充的数据 (2) method: 表示填充方式,默认值为None 1) pad/ffill: 将最后一个有效的数据向后传播,也就是说缺失值前面的一个值代替缺失值 2) backfill/bfill: 将最后一个有效的数据向前传播,也就是说用缺失值后面的一个值代替缺失值 注意: method参数和value参数只能二者选其一,不同同时使用 (3) limit: 可以连续填充的最大数量,默认为None 4. 关于0的处理 => df[df==0]=np.nan (1) 注意: 不是每次都需要处理0,但是像求平均数这类操作,0是会参与的,视情况处理了
# code14_pandas处理缺失值.py import pandas as pd import numpy as np # 1. 判断是否为缺失值 # pd.isnull() pd.notnull() ser = pd.Series([1, None, np.nan]) print(ser) print(‘-‘ * 30) print(pd.isnull(ser)) # 检查是否为空值或缺失值 print(‘-‘ * 30) print(pd.notnull(ser)) # 检查是否不是空值或缺失值 print(‘-‘ * 30) # 3. 删除含有含有缺失值/空值的行或列 # pd.dropna(axis=0,how=‘any‘,thresh=None,subset=None,inplace=False) d1 = dict(类别=[‘小说‘, ‘散文随笔‘, ‘青春文学‘, ‘传记‘], 书名=[np.nan, ‘《皮囊》‘, ‘《旅程结束时》‘, ‘《老舍自传》‘], 作者=[‘老舍‘, None, ‘张其鑫‘, ‘老舍‘]) df = pd.DataFrame(d1) print(df) print(‘-‘ * 30) drop_df = df.dropna(inplace=False) # 默认是删除有缺失值的行 print(drop_df) print(‘-‘ * 30) # 3. 填充缺失值/空值 # pd.fillna(value=None,method=None,limit=None.....) d2 = dict(A=[1, 2, 3, np.nan], B=[np.nan, 4, np.nan, 6], C=[‘a‘, 7, 8, 9], D=[np.nan, 2, 3, np.nan]) df = pd.DataFrame(d2) print(df) print(‘-‘ * 30) # (1) 全部缺失值都才采用一个value来填充 fill_value_df = df.fillna(value=66.0) # 使用66.0替换缺失值 print(fill_value_df) print(‘-‘ * 30) # (2) 指定的列使用指定的value来填充 fill_value = dict(A=4.0, B=5.0, C=6.0, D=7.0) fill_value_df = df.fillna(value=fill_value) # 给value传入字典,可以实现给指定的列填充指定的数值 print(fill_value_df) print(‘-‘ * 30) # (3) ffill : 同一列,NaN上面的值来填充 ffill_df = df.fillna(method=‘ffill‘) print(ffill_df) print(‘-‘*30) # (3) bfill : 同一列,NaN下面的值来填充 bfill_df = df.fillna(method=‘bfill‘) print(bfill_df) print(‘-‘*30)
1. pd.Series.str 这是Series的一个属性,里面有字符串方法 2. 内置字符串方法优势在于矢量化,而无需循环(如果使用使用普通Python字符串的话) df["Row_Labels"].str.len() > 4 # 该列字符串长度大于4的 ser.str.lower() # 把该列字符串都转为小写字母
1. 数组化处理 => list(ndarray) ndarray.tolist() 比如像set() 使用去重方式, ndarray报错 unhashable 2. 去重处理 (1) set(list()) (2) Series.unique() 3. 多维数组转为一维数组 (1) Python循环转化 [j for i in L for j in i] # 二维list为例子 (2) ndarray().flatten() / ndarray.reshape(-1) 4. 获得Series和DataFrame的行数了列数 (1) Series.shape[0] DataFrame.shape[1] (2) len(Series) 5. 对Series/ DataFrame进行排序 sort_values, sort_index
常用统计计算
常用统计描述
1. 如果希望一次性输出多个统计指标,比如平均值,最大值,最小值,求和等,则可以调用describe(),而不用再单独地逐个调用相应的统计方法. 2. describe(percentiles=None,include=None,exclude=None) (1) percentiles: 输出中包含的百分数,位于[0,1]之间,如果不设置该参数,则默认为[0.25,0.5,0.75],返回25%,50%,75%分位数. (2) include,exclude: 指定返回结果的形式
# code15_电影评分信息.py import numpy as np import pandas as pd df = pd.read_csv(r"./IMDB-Movie-Data.csv") # 读入csv文件 print(df.info()) print("-" * 30) # 1. 评分的平均分 mean(Rating) rating_mean = df["Rating"].mean() # 选中对应的列,然后进行求平均计算 print("df[\"Rating\"].mean():", rating_mean) print("-" * 30) # 2. 导演人数 len(set(Director)) / unique() # nums_director = len(set(df["Director"].tolist())) nums_director = len(df["Director"].unique()) # 使用 df[列属性].unique() <=> set(df[列属性].tolist()) print("len(df[\"Director\"].unique()):", len(df["Director"].unique())) print("-" * 30) # 3. 演员人数 len(set(Actors)) / unique() # 演员人数有点特殊,因为演员是一行有好几个言演员 temp_actors_list = df["Actors"].str.split(", ").tolist() # 分隔逗号, 然后称为一个二维数组 actor_list = [j for i in temp_actors_list for j in i] # 把二维的列表平铺为一维的 => Python普通做法 # 转为numpy对象,进行矢量化处理 => reshape(-1) flatten() (记得转为list类型) # 这个思路可以,但是列表中的每个元素都是list类型的,并不能展开,所以自己两重循环 actor_num = len(set(actor_list)) # 统计演员人数 print("len(set(actor_list)):", actor_num) # TypeError: unhashable type: ‘list‘ 注意不能直接对numpy进行set() => list(ndarray) ndarray.tolist() print(‘-‘ * 30) # 4. 电影时长的最大最小值 max_runtime = df[["Runtime (Minutes)"]].max() # 获得最大值 max_runtime_index = df["Runtime (Minutes)"].argmax() # 获取最大值索引 min_runtime = df["Runtime (Minutes)"].min() min_runtime_index = df["Runtime (Minutes)"].argmin() median_runtime = df["Runtime (Minutes)"].median() print("df[\"Runtime (Minutes)\"].max():", max_runtime) print("df[\"Runtime (Minutes)\"].argmax():", max_runtime_index) print("df[\"Runtime (Minutes)\"].min():", min_runtime) print("df[\"Runtime (Minutes)\"].argmin():", min_runtime_index) print("df[\"Runtime (Minutes)\"].median():", median_runtime)
# code16_电影时长和评分分布.py import numpy as np import pandas as pd # import matplotlib.pyplot as plt from matplotlib import pyplot as plt file_path = r"./IMDB-Movie-Data.csv" df = pd.read_csv(file_path) print(df.info()) # 查看资料信息 print(‘-‘ * 30) print(df.head(1)) # 查看你第一行数据 print(‘-‘ * 30) # 任务: rating,runtime分布情况 # 图形: 直方图 # 准备数据 runtime_data = df["Runtime (Minutes)"].values print(type(df["Runtime (Minutes)"])) # <class ‘pandas.core.series.Series‘> print(type(df["Runtime (Minutes)"].values)) # <class ‘numpy.ndarray‘> # 计算组数(例如5分钟作为组距) runtime_max = runtime_data.max() runtime_min = runtime_data.min() runtime_bins = (runtime_max - runtime_min) // 5 # 画图 plt.figure(figsize=(20, 8 * 3), dpi=80) plt.subplot(3, 1, 1) plt.rcParams[‘font.sans-serif‘] = [‘SimHei‘] # 用来正常显示中文标签 plt.rcParams[‘axes.unicode_minus‘] = False # 用来正常显示负号 plt.hist(runtime_data, bins=runtime_bins) # 设置刻度 => 最小值,最大值+步长,步长 plt.xticks(range(runtime_min, runtime_max + 5, 5)) plt.title("电影时长分布情况") print(‘-‘ * 30) # 下面同理绘制评分的分布图 plt.subplot(3, 1, 2) rating_data = df["Rating"].values rating_max, rating_min = rating_data.max(), rating_data.min() rating_bins = (rating_max - rating_min) // 0.5 # 评分的组距为0.5(不同的属性应该有不同的属性) # plt.hist(np.arange(rating_min, rating_max + 0.5, 0.5)) # 这个是典型的错误,因为range里面必须全部都是int # 现在为了取到0.5步长,不能使用range() 只能自己手动操作 rating_x = [] i = rating_min while i <= rating_max + 0.5: rating_x.append(i) i += 0.5 plt.hist(rating_data, bins=int(rating_bins)) plt.xticks(rating_x) plt.title("评分分布情况") plt.subplot(3, 1, 3) plt.title("评分分布情况(调整组距)") # 前面人数较少的组可以合并 => bins传入一个数组 # 1.9-3.5 这个人数少的其实可以设置为一组 rating_bins = [rating_min, rating_min + 1.6] # max(9.0) min(1.9) => 整个的距离是 7.1, 现在在减去1.6,剩余5.5的距离,然后这个5.5按0.5的组距在划分 x = rating_bins[-1] while x <= rating_max: x += 0.5 rating_bins.append(x) # 注意列表的append()和+的区别 plt.hist(rating_data, bins=rating_bins) plt.xticks(rating_bins) plt.show()
# code17_电影类型分类情况.py # 字符串离散化案例 import numpy as np import pandas as pd from matplotlib import pyplot as plt file_path = r"./IMDB-Movie-Data.csv" df = pd.read_csv(file_path) # print(df.loc[0,"Genre"]) temp_list = df["Genre"].str.split(",").tolist() # [[],[],[],...] 这样的格式 # 获得属性的列表 genre_list = list(set([j for i in temp_list for j in i])) # 构造全为0的数组 zeros_pd = pd.DataFrame(np.zeros((df.shape[0], len(genre_list))), columns=genre_list) # 给数组的每个位置赋值 => 好像并不能一行一行的处理 # for i in range(df.shape[0]): # for j in temp_list[i]: # zeros_pd.loc[i,j]=1 for i in range(df.shape[0]): zeros_pd.loc[i,temp_list[i]]=1 # 直接可以一整行的处理 # 统计df => 指定axis genre_count = zeros_pd.sum(axis=0) # 指定axis进行求和 print(genre_count) # 得到一个Series print(‘-‘*30) plt.rcParams[‘font.sans-serif‘] = [‘SimHei‘] # 用来正常显示中文标签 plt.rcParams[‘axes.unicode_minus‘] = False # 用来正常显示负号 plt.figure(figsize=(20*2,8*2),dpi=80) plt.subplot(2,1,1) plt.bar(genre_count.index,genre_count.values) plt.title("电影类型统计") plt.subplot(2,1,2) plt.title("电影类型统计(排序)") # 排序 genre_count.sort_values(inplace=True) plt.bar(genre_count.index,genre_count.values,width=0.4,color="orange") plt.show()
读写文本数据
CSV文件是一种纯文本文件,可以使用任何文本编辑器进行编辑,它支持追加模式(a),节省内存开销.
因为CSV文件具有诸多的优点,所以在很多时候会将数据保存在CSV文件中.
1. Pandas提供了 (1) read_csv() 和 (2) to_csv(),分别用于读取CSV文件和写入CSV文件 2. 通过to_csv()将数据写入CSV文件 to_csv(path_or_buf=None,index=True,sep=‘,‘,.....) (1)
读写Excel数据
读取HTML表格数据
读写数据库
计算的时候总共分3步,1到2是第二组......lower: i. 这组数据中的小值 higher: j. 这组数据中的大值,fraction 是第三步中的小数部分,意思是当前这组数据的0到1的分位数