数据分析之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各个元素上