数据分析之pandas
一.Pandas
1.1简介
pandas是一个强大的Python数据分析的工具包,它是基于Numpy构建的,相当于Numpy的升级版本(自己瞎说的)正因pandas的出现,让Python语言也成为使用最广泛而且强大的数据分析环境之一
1.2 pandas 的主要功能:
具备对其功能的数据结构 DataFrame, Series 集成时间序列化功能 提供丰富的数学运算和操作 灵活处理缺失数据的方法
安装:pip install pandas (我们已经安装Anaconda 直接导入就行乐)
引用方法:
import pandas as pd (约定俗成)
2.Series
Series是一种类似于一维数组的对象,由一组数据和一组与之相关的数据标签(索引)组成。
(1)创建方法
Pandas的相关使用
import pandas as pd # 1.第一种 不指定索引 自动指定0起始缩引 l1 = [6,9,2,3,4,5,6] pd.Series(l1) 0 6 1 9 2 2 3 3 4 4 5 5 6 6 dtype: int64 ? # 将数组索引以及数组的值打印出来,索引在左,值在右, # 由于没有为数据指定索引,于是会自动创建一个0到N-1(N为数据的长度)的整数型索引, # 取值的时候可以通过索引取 ? ‘a‘,‘b‘,‘c‘ # 第二种 指定索引 左索引 右对应的值 l2 = [2,3,4,6,7] pd.Series(l2,index=[‘a‘,‘b‘,‘c‘,‘b‘,‘e‘]) a 2 b 3 c 4 b 6 e 7 dtype: int64 的数组 # 第三种 创建一个值都是0的数组 pd.Series(0,index=[‘a‘,‘b‘,‘c‘]) a 0 b 0 c 0 dtype: int64 # 2 。缺失值的使用和应用场景 # 对于Series,其实我们可以认为它是一个长度固定且有序的字典, # 因为它的索引和数据是按位置进行匹配的, # 像我们会使用字典的上下文,就肯定也会使用Series Series # (1)dropna() # 过滤值为NaN的行 # (2)fill() # 田聪缺失值 # (3)isnull() # 返回布尔值数组,缺失值对应为True # (4)notnull # 返回布尔值数组,缺失值对应为False tu = {"kk":18,"cc":19,"yy":20,"tt":21} # 将字典通过panda # 第一步 ,创建一个字典,通过Series方式创建一个Series 对像 stu = {"kk":18,"cc":19,"yy":20,"tt":21} # 将字典通过pandas的Series 转成数组对象 obj = pd.Series(stu) obj kk 18 cc 19 yy 20 tt 21 dtype: int64 我们自己传入一个么有的key 则回出现 一个uu:NaN # 第二步 定义一个索引变量 a = {"kk","cc","yy","uu"} # 我们自己传入一个么有的key 则回出现 一个uu:NaN # 第三步 将a 传入作为索引 stu1 =pd.Series(stu,index=a) stu1 cc 19.0 yy 20.0 uu NaN kk 18.0 dtype: float64# 我们自己传入一个么有的key 则回出现 一个uu:NaN 返回的是 一个确实值 ? # 综合上面的代码我们可以 通过isnull() 进行判断是否有缺失值 # 1.isnull() stu1.isnull() 3 缺失值返回True cc False yy False uu True kk False dtype: bool# 2 notnull() stu1.notnull() # # >>> # 缺失值返回Fasle 不是缺失值返回True cc True yy True uu False kk True dtype: bool 方法:直接 # 3 方法:直接过滤缺失值 》》》 布尔类型索引 ? stu1[stu1.notnull()] cc 19.0 yy 20.0 kk 18.0 dtype: float64
(2)Series 的特性
a.从ndarray类创建 Series:Series(arr)
与标量(数字):str*2 两个Seriesy运算 通用函数:np.ads(sr) 布尔值过滤:Sr[sr>0] 统计函数:mean(), sum(), cusum()
b.支持字典的特性:
从字典创建Series:Series(dic), In运算:‘a‘in sr、for x in sr 键索引:sr[‘a‘],sr[[‘a‘,‘b‘,‘d‘]] 键切片:sr[‘a‘:‘c‘] 其他函数:get(‘a‘,default=0)等
整数索引
pandas 当中的整数索引对象 代码演示:
obj1 = pd.Series(np.arange(10) # 0,1,2,3,4,5,6,7,8,9 obj2 = obj1[3:].copy() obj2 # 代码演示 obj1 = pd.Series(np.arange(10) # 0,1,2,3,4,5,6,7,8,9 obj2 = obj1[3:].copy() obj2 ? 3 3 4 4 5 5 6 6 7 7 8 8 9 9 dtype: int32 重 # obj2[1] obj2[3]取标签是可以i的 不要自己想当然 验证 # 无法取出obj2的值 # 解决方案 # (1)loc属性 》》》以标签解释 # (2)iloc属性 》》》 以下标解释 obj2.loc[4] # 这个就是标签 和obj[3] 是一样的取值方法 # obj2.iloc[0] 重新排列的数据索引从0开始的 [0] 可以取值3 [1] 4 4
Series 数据对齐
pandas在运算时,会按照索引进行对齐然后计算,如果存在不同的索引,则结果表的索引是两个操作数索引的并集
实列:
s1 = pd.Series([11,22,33],index=[‘a‘,‘b ‘,‘c‘]) # Series数据对齐 s1 = pd.Series([11,22,33],index=[‘a‘,‘b ‘,‘c‘]) s2 = pd.Series([44.,55,66],index=[‘d‘,‘c‘,‘a‘]) s1+s2 a 77.0 b NaN c 88.0 d NaN dtype: float64 ue=0) # s1 和s2 的索引不一致, 所以最终的运行通过index b和d没有对应的就会 值就会返回NaN 是一个确实值 # 解决方案 我们将两个Series 对象相加sh8将缺失值设置为 0 s1 = pd.Series([11,22,33],index=[‘a‘,‘b‘,‘c‘]) s3 = pd.Series([100,200,300,500],index=[‘c‘,‘a‘,‘b‘,‘e‘]) s1.add(s3,fill_value=0) a 211.0 b 322.0 c 133.0 e 500.0 dtype: float64
# 将e 的对应到s1缺失值设置为0 =500+0 结果500
# 灵活算法add,sub,div,mul
3.DataFrame
DataFrame是一种表格的数据结构,相当于一个二维数组, 含有一组有序的列,
可以看做是由Series组成的字典,并且共用一个索引
创建方法:
创建一个DataFrame数组可以有多种方式,其中最为常用的方式就是利用包含等长度列表或Numpy数组的字典来形成DataFrame:
# 第一种
# 第一种 pd.DataFrame({"one":[1,2,3,4],"two":[6,7,8,9]}) # DataFrame 会自动分配索引,并且按按照排列的顺序排列 one two 0 1 6 1 2 7 2 3 8 3 4 9 # 指定列 可以通过columns 参数指定顺序排列data = pd.DataFrame({"one":[1,2,3,4],"two":[6,7,8,9]})pd.DataFrame(data,columns=["two","one"]) two one 0 6 1 1 7 2 2 8 3 3 9 4 # 第二种 # 第二种 pd.DataFrame({"n1":pd.Series([1,2,3],index=[‘a‘,‘b‘,‘c‘]),‘n2‘:pd.Series([9,7,6],index=[‘c‘,‘a‘,‘b‘])}) n1 n2 a 1 7 b 2 6 c 3 9 以上创建方法简单了解就可以,因为在实际应用当中更多是读数据,不需要自己手动创建 查数据 index 获取行索引 columns 获取列索引 T 转置 columns 获取列索引 values 获取值索引 describe 获取快速统计
结果
df.index # 获取索引 Index([‘a‘, ‘b‘, ‘c‘], dtype=‘object‘) df.columns df.columns Index([‘n1‘, ‘n2‘], dtype=‘object‘) df.T ? a b c n1 1 2 3 n2 7 6 9 s df.values ? array([[1, 7], [2, 6], [3, 9]], dtype=int64)
df.describe() ) n1 n2 count 3.0 3.000000 mean 2.0 7.333333 std 1.0 1.527525 min 1.0 6.000000 25% 1.5 6.500000 50% 2.0 7.000000 75% 2.5 8.000000 max 3.0 9.000000
切片和索引
DataFrame有行索引和列索引。 DataFrame同样可以通过标签和位置两种方法进行索引和切片。 DataFrame使用索引切片: 方法1:两个中括号,先取列再取行。 df[‘A‘][0] 方法2(推荐):使用loc/iloc属性,一个中括号,逗号隔开,先取行再取列。 loc属性:解释为标签 iloc属性:解释为下标 向DataFrame对象中写入值时只使用方法2 行/列索引部分可以是常规索引、切片、布尔值索引、花式索引任意搭配。(注意:两部分都是花式索引时结果可能与预料的不同)
# 获取数据源
pd.read_csv(‘文件路径‘)
# 获取数据源 f = pd.read_csv(‘./douban_movie.csv‘) f
#
f.head() # 读取前面四条数据
f.tail() # 读取后面四条数据
f.to_csv(‘./aaa.csv‘) # 重保存一分到我们的当前文件
f.to_csv(‘./aaa.csv‘,index=False) # 重保存一分到我们的当前文件 index=False 去除保存的索引,
用因为他会默认加索引 只需要一个index 即可
作业:
2. pd.read_html
pandas 计算历年nba 球队获取总冠军的次数
import pandas as pd res=pd.read_html(‘https://baike.baidu.com/item/NBA%E6%80%BB%E5%86%A0%E5%86%9B/2173192?fr=aladdin‘) res
(1)获取的数据是两张列表
表一
[ 0 1 2 3 4 5 年份 比赛日期 冠军 总比分 亚军 FMVP 4.16-4.22 费城勇士队 4-1 芝加哥牡鹿队 无 4.10-4.21 巴尔的摩子弹队 4-2 费城勇士队 无 4.4-4.13 明尼阿波利斯湖人队 4-2 华盛顿国会队 无 4.8-4.23 明尼阿波利斯湖人队 4-2 塞拉库斯民族队 无 .. ... ... ... ... ... ... 6.5-6.17 金州勇士队 4-2 克里夫兰骑士队 安德烈·伊戈达拉 6.3-6.20 克里夫兰骑士队 4-3 金州勇士队 勒布朗·詹姆斯 6.2-6.13 金州勇士队 4-1 克利夫兰骑士队 凯文·杜兰特 6.1-6.9 金州勇士队 4-0 克利夫兰骑士队 凯文·杜兰特 5.31-6.14 多伦多猛龙队 4-2 金州勇士队 科怀·伦纳德]
表二
[74 rows x 6 columns], 0 1 2 3 0 联盟 赛区 球队 夺冠次数 东部联盟 大西洋 波士顿凯尔特人队 17 西部联盟 太平洋 洛杉矶湖人队 16 西部联盟 太平洋 金州勇士队 [1] 6 东部联盟 中部 芝加哥公牛队 6 西部联盟 西南 圣安东尼奥马刺队 5 东部联盟 大西洋 费城76人队 3 东部联盟 中部 底特律活塞队 3 东部联盟 东南 迈阿密热火队 3 东部联盟 大西洋 纽约尼克斯队 2 西部联盟 西南 休斯敦火箭队 2 西部联盟 太平洋 萨克拉门托国王队 1 东部联盟 东南 亚特兰大老鹰队 1 东部联盟 中部 密尔沃基雄鹿队 1 西部联盟 西北 波特兰开拓者队 1 东部联盟 东南 华盛顿奇才队 1 西部联盟 西北 俄克拉荷马城雷霆队(西雅图超音速) 1 西部联盟 西南 达拉斯小牛队 1 东部联盟 中部 克里夫兰骑士队 1 东部联盟 大西洋 多伦多猛龙队 1 东部联盟 大西洋 布鲁克林篮网队 0 东部联盟 中部 印第安纳步行者队 0 东部联盟 东南 夏洛特黄蜂队 0 东部联盟 东南 奥兰多魔术队 0 西部联盟 太平洋 洛杉矶快船队 0 西部联盟 太平洋 菲尼克斯太阳队 0 西部联盟 西北 丹佛掘金队 0 西部联盟 西北 明尼苏达森林狼队 0 西部联盟 西北 犹他爵士队 0 西部联盟 西南 孟菲斯灰熊队 0 西部联盟 西南 新奥尔良鹈鹕队 0 已撤销 已撤销 巴尔的摩子弹 1 夺冠年份 1957、1959-1966、1968-1969、1974、 1976、1981、1984、... 1949-1950、1952-1954、1972、1980、1982、 1985、1987-... 1947、1956、1975、2015、2017-2018 1991-1993、1996-1998 1999、2003、2005、2007、2014 1955、1967、1983 1989-1990、2004 2006、2012、2013 1970、1973 1994-1995 1951 1958 1971 1977 1978 1979 2011 2016 2019 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN 1948(该队并非现奇才队前身) ]
(2)我们只要第一张表
res1 = res[0] # 获取第一张冠军的表
(3) 将索引为0的这一条数据 赋值给 列名"
res1.columns = res1.iloc[0] res1 # 将索引为0的这一条数据 赋值给 列名"
将索引为0的这一条数据 赋值给 列名"
(4)# 统计个数 res1.groupby(‘冠军‘).size() 再 进行排列asc=True 默认识升序 我们要降序
# res1.groupby(‘冠军‘).size().sort_values(ascending=False) # res1.groupby(‘冠军‘).size().sort_values(desc) 注意desc 在pandas 中用asc=False 而且要全写不能简写 res1.groupby(‘冠军‘).size().sort_values(ascending=False)
4.时间对象处理
时间序列类型
时间戳:特定时刻 固定时期:如2019年1月 时间间隔:起始时间-结束时间
Python库:datatime
- date、time、datetime、timedelta
- dt.strftime()
- strptime()
灵活处理时间对象:dateutil包
- dateutil.parser.parse()
import dateutil dateutil.parser.parse("2019 Jan 2nd") # 这中间的时间格式一定要是英文格式 运行结果: datetime.datetime(2019, 1, 2, 0, 0)
成组处理时间对象:pandas
- pd.to_datetime([‘2018-01-01‘, ‘2019-02-02‘])
pd.to_datetime([‘2018-03-01‘,‘2019 Feb 3‘,‘08/12-/019‘]) 运行结果: DatetimeIndex([‘2018-03-01‘, ‘2019-02-03‘, ‘2019-08-12‘], dtype=‘datetime64[ns]‘, freq=None) # 产生一个DatetimeIndex对象 # 转换时间索引 ind = pd.to_datetime([‘2018-03-01‘,‘2019 Feb 3‘,‘08/12-/019‘]) sr = pd.Series([1,2,3],index=ind) sr 运行结果: 2018-03-01 1 2019-02-03 2 2019-08-12 3 dtype: int64 通过以上方式就可以将索引转换为时间
补充: pd.to_datetime([‘2018-03-01‘,‘2019 Feb 3‘,‘08/12-/019‘]).to_pydatetime() 运行结果: array([datetime.datetime(2018, 3, 1, 0, 0), datetime.datetime(2019, 2, 3, 0, 0), datetime.datetime(2019, 8, 12, 0, 0)], dtype=object) # 通过to_pydatetime()方法将其转换为array数组
产生时间对象数组:data_range
- start 开始时间
- end 结束时间
- periods 时间长度
- freq 时间频率,默认为‘D‘,可选H(our),W(eek),B(usiness),S(emi-)M(onth),(min)T(es), S(econd), A(year),…
pd.date_range("2019-1-1","2019-2-2") 运行结果: DatetimeIndex([‘2019-01-01‘, ‘2019-01-02‘, ‘2019-01-03‘, ‘2019-01-04‘, ‘2019-01-05‘, ‘2019-01-06‘, ‘2019-01-07‘, ‘2019-01-08‘, ‘2019-01-09‘, ‘2019-01-10‘, ‘2019-01-11‘, ‘2019-01-12‘, ‘2019-01-13‘, ‘2019-01-14‘, ‘2019-01-15‘, ‘2019-01-16‘, ‘2019-01-17‘, ‘2019-01-18‘, ‘2019-01-19‘, ‘2019-01-20‘, ‘2019-01-21‘, ‘2019-01-22‘, ‘2019-01-23‘, ‘2019-01-24‘, ‘2019-01-25‘, ‘2019-01-26‘, ‘2019-01-27‘, ‘2019-01-28‘, ‘2019-01-29‘, ‘2019-01-30‘, ‘2019-01-31‘, ‘2019-02-01‘, ‘2019-02-02‘], dtype=‘datetime64[ns]‘, freq=‘D‘)
时间序列
时间序列就是以时间对象为索引的Series或DataFrame。datetime对象作为索引时是存储在DatetimeIndex对象中的。
# 转换时间索引 dt = pd.date_range("2019-01-01","2019-02-02") a = pd.DataFrame({"num":pd.Series(random.randint(-100,100) for _ in range(30)),"date":dt}) # 先生成一个带有时间数据的DataFrame数组 a.index = pd.to_datetime(a["date"]) # 再通过index修改索引
特殊功能:
- 传入“年”或“年月”作为切片方式
- 传入日期范围作为切片方式
- 丰富的函数支持:resample(), strftime(), ……
- 批量转换为datetime对象:to_pydatetime()
a.resample("3D").mean() # 计算每三天的均值 a.resample("3D").sum() # 计算每三天的和 ...
5.数据分组和聚合方法
上面的案列做的简单介绍
6.其他常用方法
pandas常用方法(适用Series和DataFrame)
- mean(axis=0,skipna=False)
- sum(axis=1)
- sort_index(axis, …, ascending) # 按行或列索引排序
- sort_values(by, axis, ascending) # 按值排序
- apply(func, axis=0) # 将自定义函数应用在各行或者各列上,func可返回标量或者Series
- applymap(func) # 将函数应用在DataFrame各个元素上
- map(func) # 将函数应用在Series各个元素上