Pandas简介
一、什么是Pandas
当大家谈论到数据分析时,提及最多的语言就是Python和SQL
而Python之所以适合做数据分析,就是因为他有很多强大的第三方库来协助
pandas就是其中之一,它是基于Numpy构建的,正因pandas的出现,让Python语言也成为使用最广泛而且强大的数据分析环境之一。
如果说没有pandas的出现,目前的金融数据分析领域还应该是R语言的天下。
二、Pandas能干什么
1.具备对应其功能的数据结构DataFrame,Series
2.集成时间序列功能
3.提供丰富的数学运算和操作
4.灵活处理缺失数据
.....
以上就是pandas能完成的一些基础操作,当然并不完全,下面就来看看pandas到底是怎么用的。
三、怎么用Pandas
安装
pip install pandas
引用
import pandas as pd
四、Pandas基础使用
Series
Series是一种类似于一维数组的对象,由一组数据和一组与之相关的数据标签(索引)组成。在数据分析的过程中非常常用。
1. 创建方法
import pandas as pd
1.直接传列表的形式,创建pandas数据
pa1 = pd.Series([1,2,3,4,5])
print(type(pa1))
print(pa1)
执行结果如下:
<class 'pandas.core.series.Series'>
0 1
1 2
2 3
3 4
4 5
dtype: int64
总结:将数组索引以及数组的值打印出来,索引在左,值在右,由于没有为数据指定索引,于是会自动创建一个0到N-1(N为数据的长度)的整数型索引,取值的时候可以通过索引取
2. 传列表,同时指定索引
pa2 = pd.Series([1,2,3,4,5],index=[1,2,3,4,5])
print(pa2)
pa3 = pd.Series([1,2,3,4,5],index=["1","2","3","4","5"])
print(pa3)
pa4 = pd.Series(np.arange(5),index=list('12345'))
print(pa4)
总结:自定义索引,index是一个索引列表,里面包含的是字符串,依然可以通过默认索引取值。
3.以字典的形式传值
pa5 = pd.Series({'a':1,'b':2})
print(pa5)
执行结果如下:
a 1
b 2
dtype: int64
总结:以字典的key作为索引,(相当于可以指定索引)
4.创建一个值全部为0的数组
pa6 = pd.Series(0,index=[1,2,3,4,5])
print(pa6)
执行结果如下:
1 0
2 0
3 0
4 0
5 0
dtype: int64
总结:Series创建的pandas数据对象,索引与值必须是一一对应的个数
对于Series,其实我们可以认为它是一个长度固定且有序的字典,因为他的索引和数据是按照位置进行匹配的,像我们会使用字典的上下文,就肯定会使用Series
2.Series基础运算使用
-
利用ndarry创建Series对象
nparr = np.arange(5) print(nparr) pa7 = pd.Series(nparr)# ndarray创建Series对象 print(pa7) 执行结果如下: [0 1 2 3 4] 0 0 1 1 2 2 3 3 4 4 dtype: int32
-
与标量(数字)进行运算
pa8 = pa7 * 2 # pa7对象中的每一个数据值都*2 print(pa8) 执行结果如下: 0 0 1 2 2 4 3 6 4 8 dtype: int32
-
两个Series对象数据进行运算
pa9 = pa7 * pa8 print(pa9) 执行结果如下: 0 0 1 2 2 8 3 18 4 32 dtype: int32
-
布尔值过滤----通过numpy的布尔值索引
print(pa9>2) pa10 = pa9[pa9>2] print(pa10) 执行结果如下: 0 False 1 False 2 True 3 True 4 True dtype: bool 2 8 3 18 4 32 dtype: int32
-
统计函数
# 1。mean()---求平均值 print(pa9.mean()) # 2.sum()---求和 print(pa9.sum()) # 3.cumsum()---类似于斐波那契数列 print(pa9.cumsum()) 执行结果如下: 12.0 60 0 0 1 2 2 10 3 28 4 60 dtype: int32
3.Series 支持字典的特性
-
从字典创建Series:Series(dic)
dic = {'a':1,'b':2,'c':3,'d':4} pa11 = pd.Series(dic)
-
in 运算
istrue = 'a' in pa11 print(istrue) istrue1 = 'e' in pa11 print(istrue1) 执行结果如下: True False
-
键索引
value1 = pa11['a'] print(value1) value2 = pa11.get('c') print(value2) # pall['e'] # 取不到会报错(不管是否是get) # 但是可以给get设置默认值(default) value3 = pa11.get('e',default=0) print(value3) # 可以通过键取多个。但是要记得用列表 value4 = pa11[['a','d']] print(value4)
-
键切片(顾头又顾尾)
pall['a':'c']
4.整数索引
pandas当中的整数索引对象可能会让初次接触它的人很懵逼,接下来通过代码演示
iloc:解释为下标
loc:解释为标签
pa13 = pd.Series(np.arange(10)) #利用ndarray创建Series对象数据
print(pa13)
pa14 = pa13[3:] #相当于列表中的切片取值
print(pa14)
# 以上只是在切片索引取值,那如果我们的需求是,只取其中的某一个值?---我们会发现就出现问题了
value0 = pa13[0] # 在我们原本定义的pa13对象数据,单个取值还是没有问题的
print(value0)
# value1 = pa14[0] # 知道这里我们发信报错了,为什么?
'''
loc属性:以标签做为解释
iloc属性:以下标作为解释,相当于索引
'''
# 当我们直接用pa13[0]取值的时候,实际上是默认以标签作为解释的loc
# 下面我们来用ilog来做实验
value2 = pa13.loc[3]
print(value2) # 没有任何问题的
''' 以下两行代码我们法相报错了。因为切片取得的没有标签为1的值
value3 = pa14.loc[1]
print(value3)
'''
value3 = pa14.iloc[1]
print(value3) # 打印结果,没有任何问题,按索引来取值
5. Series数据对齐
pandas在运算时,会按索引进行对齐然后计算。如果存在不同的索引,则结果的索引是两个操作数索引的并集。
s1 = pd.Series([12,23,34], index=['c','a','d'])
s2 = pd.Series([11,20,10], index=['d','c','a',])
s_sum = s1 + s2
print(s_sum)
执行结果如下:
a 33
c 32
d 45
dtype: int64
# 当两个数据对象索引不同时
s4 = pd.Series([11,20,10,14], index=['d','c','a','b'])
s_sum1 = s1 + s4
print(s_sum1)
# s1 和 s4的索引不一致,所以最终的运行会发现b索引对应的值无法运算,就返回了NaN,一个缺失值
执行结果如下:
a 33.0
b NaN
c 32.0
d 45.0
dtype: float64
# 将两个Series对象相加时将缺失值设为0
s_sum2 = s1.add(s4,fill_value=0)
print(s_sum2)
执行结果如下:
a 33.0
b 14.0
c 32.0
d 45.0
dtype: float64
DateFrame
DataFrame是一个表格型的数据结构,相当于是一个二维数组,含有一组有序的列。他可以被看做是由Series组成的字典,并且共用一个索引。接下来就一起来见识见识DataFrame数组的厉害吧!!!
1. 创建方式
创建一个DataFrame数组可以有多种方式,其中最为常用的方式就是利用包含等长度列表或Numpy数组的字典来形成DataFrame
pd.DataFrame({'a':pd.Series(np.arange(10)),"b":pd.Series(np.arange(10))})
执行结果如下:
a b
0 0 0
1 1 1
2 2 2
3 3 3
4 4 4
5 5 5
6 6 6
7 7 7
8 8 8
9 9 9
data = pd.DataFrame({'one':[1,2,3,4],'two':[4,3,2,1]})
pd.DataFrame(data,columns=['one','two'])
执行结果如下:
one two
0 1 4
1 2 3
2 3 2
3 4 1
pd.DataFrame({'one':pd.Series([1,2,3],index=['a','b','c']),'two':pd.Series([1,2,3],index=['b','a','c'])})
执行结果如下:
one two
a 1 2
b 2 1
c 3 3
-
不指定索引,自动添加
产生的DataFrame会自动为Series分配所索引,并且列会按照排序的顺序排列 其实也就是字典的key作为列索引
data1 = pd.DataFrame({'one':[1,2,3,4],'two':[4,3,2,1]}) print(data1) 执行结果如下: one two 0 1 4 1 2 3 2 3 2 3 4 1
-
指定列
指定列时,列索引一定要是字典中的key,可以不按照顺序
data2 = pd.DataFrame({'one':[1,2,3,4],'two':[4,3,2,1]}) data3 = pd.DataFrame(data2,columns=['one','two']) print(data3) 执行结果如下: one two 0 1 4 1 2 3 2 3 2 3 4 1
-
指定行索引
data4 = pd.DataFrame({'one':pd.Series([1,2,3],index=['a','b','c']),'two':pd.Series([1,2,3],index=['b','a','c'])}) print(data4) 执行结果如下: one two a 1 2 b 2 1 c 3 3
以上创建方法简单了解就可以,因为在实际应用当中更多是读数据,不需要自己手动创建
2. 查看数据
常用属性和方法:
- index 获取行索引
- columns 获取列索引
- T 转置
- values 获取值索引
- describe 获取快速统计
print(data4) # 有这样一个数组
row_index = data4.index # 1.获取行索引
print(row_index)
columns_index = data4.columns # 2.获取列索引
print(columns_index)
T_data = data4.T # 3.转置(类似于numpy中的T,将行列转换)
print(T_data)
value_index = data4.values # 4.获取值索引,得到一个数组
print(value_index)
describe_data = data4.describe() # 5.快速统计
print(describe_data)
'''结果
one two
count 3.0 3.0 数据统计
mean 2.0 2.0 平均值
std 1.0 1.0 标准差
min 1.0 1.0 最小值
25% 1.5 1.5 四分之一均值
50% 2.0 2.0 二分之一均值
75% 2.5 2.5 四分之三均值
max 3.0 3.0 最大值
'''
3.索引和切片
- DataFrame有行索引和列索引。
- DataFrame同样可以通过标签和位置两种方法进行索引和切片。
-
方法一:
两个中括号,无论是先取行还是先取列都可以。
# tushare是python的一个库,它是用来获取数据的(远程、本地、数据库) data5 = ts.get_k_data("000001") # 000001 是中国平安的股票数据 data6 = data5['open'][0] # 先取列再取行 print(data6) 执行及如果如下: 8.737 data7 = data5[:10]['open']# 先去行再取列 data7 执行结果如下: 0 8.737 1 8.747 2 8.834 3 8.873 4 8.873 5 8.834 6 8.844 7 8.805 8 8.766 9 8.757 Name: open, dtype: float64
-
方法二:使用loc/iloc属性
一个中括号,逗号隔开,先取行再取列。
data.iloc[0]['date'] 执行结果:'2017-06-06'
data8 = data5.loc[:10,"open":'low'] # loc 用标签取 print(data8) 执行结果: open close high low 0 8.737 8.766 8.786 8.718 1 8.747 8.854 8.873 8.737 2 8.834 8.854 8.873 8.805 3 8.873 8.873 8.941 8.844 4 8.873 8.834 8.912 8.825 5 8.834 8.844 8.863 8.776 6 8.844 8.805 8.854 8.766 7 8.805 8.766 8.805 8.757 8 8.766 8.747 8.805 8.737 9 8.757 8.854 8.873 8.747 10 8.844 8.844 8.883 8.815
data9 = data5.iloc[:10,1:5] # iloc 用下表索引取 print(data9) 执行结果: open close high low 0 8.737 8.766 8.786 8.718 1 8.747 8.854 8.873 8.737 2 8.834 8.854 8.873 8.805 3 8.873 8.873 8.941 8.844 4 8.873 8.834 8.912 8.825 5 8.834 8.844 8.863 8.776 6 8.844 8.805 8.854 8.766 7 8.805 8.766 8.805 8.757 8 8.766 8.747 8.805 8.737 9 8.757 8.854 8.873 8.747
时间对象处理
处理时间对象可能是我们在进行数据分析的过程当中最常见的,我们会遇到各种格式的时间序列,也需要处理各种格式的时间序列,但是一定不能对这些数据懵逼,我们需要找到最合适的招式来处理这些时间。接下来就一起来看吧!!!
1. 时间序列类型
- 时间戳:特定时刻
- 固定时期:如2020年1月
- 时间间隔:起始时间-结束时间
2. python库:datetime
- date、datetime、timedelta
# datetime.date() # date对象
today = datetime.date.today() # 获取当天日期,返回date对象
print(today)
t1 = datetime.date(2019,4,18) # 设置时间格式为datetime.date
print(t1)
# datetime.datetime() # datetime对象
now = datetime.datetime.now() # 获取当天日期,返回datetime对象
print(now)
t2 = datetime.datetime(2019,4,18) # 设置时间格式为datetime.datetime
print(t2)
# datetime.timedelta() # 时间差
today = datetime.datetime.today()
print(today)
yestoday = today - datetime.timedelta(1) # 以时间做运算
print(yestoday)
- strftime()---时间格式转换为字符串
# 将时间格式转换为字符串
print(yestoday)
s_yestoday = yestoday.strftime("%Y-%m-%d")
print(s_yestoday)
- strptime
# 将日期字符串转成datetime时间格式,第二个参数由时间格式决定
date_time = datetime.datetime.strptime('2019-04-18','%Y-%m-%d')
print(date_time)
3.dateutile包
-
deteutil .parser.parse()
import dateutil # 将字符串格式的日期转换为datetime对象 date = '2019 Jan 2nd' t3 = dateutil.parser.parse(date) print(t3)
4. to_datetime 处理多个时间对象
# 转换单个时间数据是返回Timestamp对象,转换多个时间数据返回DatetimeIndex对象
date1 = datetime.datetime(2019, 4, 18, 12, 24, 30)
date2 = '2019-04-18'
# Timestamp对象
t4 = pd.to_datetime(date1)
print(t4)
t5 = pd.to_datetime(date2)
print(t5)
# DatetimeIndex对象
t6 = pd.to_datetime([date1,date2])
print(t6)
-
将索引设置为时间序列
ind = pd.to_datetime(['2018-03-01','2019 Feb 3','08/12-/2019']) sr = pd.Series([1,2,3],index=ind) print(sr)
5. 产生事件对象数组:date_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",freq="B")
执行结果:
DatetimeIndex(['2019-01-01', '2019-01-02', '2019-01-03', '2019-01-04',
'2019-01-07', '2019-01-08', '2019-01-09', '2019-01-10',
'2019-01-11', '2019-01-14', '2019-01-15', '2019-01-16',
'2019-01-17', '2019-01-18', '2019-01-21', '2019-01-22',
'2019-01-23', '2019-01-24', '2019-01-25', '2019-01-28',
'2019-01-29', '2019-01-30', '2019-01-31', '2019-02-01'],
dtype='datetime64[ns]', freq='B')
6. 时间序列
时间序列就是以时间对象为索引的Series或dataFrame。
datetime对象作为索引的是存储再Datetimeindex对象中的
# 转换时间索引
dt = pd.date_range("2019-01-01","2019-01-04")
print(dt)
执行结果:
DatetimeIndex(['2019-01-01', '2019-01-02', '2019-01-03', '2019-01-04',
dtype='datetime64[ns]', freq='D')
# 生成一个带有时间数据的DataFrame数组
a = pd.DataFrame({"num":pd.Series(np.random.randint(-100,100) for _ in range(5)),"date":dt})
print(a)
执行结果:
num date
0 -12 2019-01-01
1 25 2019-01-02
2 2 2019-01-03
3 61 2019-01-04
4 -27 2019-01-05
# # 通过index修改行索引
a.index = pd.to_datetime(a["date"])
print(a)
执行结果:
num date
date
2019-01-01 -12 2019-01-01
2019-01-02 25 2019-01-02
2019-01-03 2 2019-01-03
2019-01-04 61 2019-01-04
特殊功能:
- 传入”年“或”月“作为切片方式
- 传入日期范围作为切片方式
- 丰富的函数支持:resample(),strftime()
a.resample("3D").mean() # 计算每三天的均值
a.resample("3D").sum() # 计算每三天的和
注意:时间序列的处理再数据分析当中非常重要,但是有时候时间的格式不一致有会让人非常烦躁,只要把以上秘籍全部都学会,就可以把时间序列制服的服服帖帖