Series和DataFrame是Pandas中最重要的两个数据结构,Series类似numpy中的一维数组,DataFrame类似numpy中的二维数据,它们除了可以使用numpy中的方法外,还增加了索引这个功能,DataFrame中有行的index和列的index。
1、创建Series
Series除了包含一个数组外,还有一个对数组每个元素的一个index索引,这个索引默认从0开始,当然也可以自己定义。
- 通过一个列表创建Series
s = pd.Series([11,22,33,"fgfff",np.nan])
print(s)
# 0 11
# 1 22
# 2 33
# 3 fgfff
# 4 NaN
# dtype: object
左边就是默认的索引,从0开始
- 通过列表创建Series,同时指定一个index
s = pd.Series([2,3,5,4,3,6,5,3],index["一","二","三","四","五","六","七","八"])
print(s)
# 一 2
# 二 3
# 三 5
# 四 4
# 五 3
# 六 6
# 七 5
# 八 3
# dtype: int64
- 使用一个日期来所谓index
date = pd.date_range("2017-1-1",periods=8)
s = pd.Series([2,3,5,4,3,6,5,3],index=date)
print(s)
# 2017-01-01 2
# 2017-01-02 3
# 2017-01-03 5
# 2017-01-04 4
# 2017-01-05 3
# 2017-01-06 6
# 2017-01-07 5
# 2017-01-08 3
- 通过index和values来查看Series的index和元素
date = pd.date_range("2017-1-1", periods=8)
s = pd.Series([2, 3, 5, 4, 3, 6, 5, 3], index=date)
print(s.index)
print(s.values)
# DatetimeIndex(['2017-01-01', '2017-01-02', '2017-01-03', '2017-01-04',
# '2017-01-05', '2017-01-06', '2017-01-07', '2017-01-08'],
# dtype='datetime64[ns]', freq='D')
# [2 3 5 4 3 6 5 3]
注意:在创建Series的时候,传递的index的数量和数组元素的数量必须一致,index中可以由重复的index。
2、创建DataFrame
DataFrame和numpy的二维数组类似,它在行和列上都有索引,类似excel一样。
传递一个二维数组可以创建一个DataFrame
data = pd.DataFrame(np.arange(0, 12).reshape((3, 4)))
print(data)
# 0 1 2 3
#0 0 1 2 3
#1 4 5 6 7
#2 8 9 10 11
也可以指定index和columns。
data = pd.DataFrame(np.arange(0,12).reshape((3,4)),
index=pd.date_range("2017-1-1",periods=3),
columns=["A","B","C","D"])
print(data)
# A B C D
# 2017-01-01 0 1 2 3
# 2017-01-02 4 5 6 7
# 2017-01-03 8 9 10 11
和Series类似,也可以使用字典来创建DataFrame
data = pd.DataFrame({"A":[1,2,3],
"B":["呵呵","哈哈","嘿嘿"],
"C":["昨天","今天","明天"]})
print(data)
# A B C
# 0 1 呵呵 昨天
# 1 2 哈哈 今天
# 2 3 嘿嘿 明天
这种方式创建的DataFrame,可以看到index是默认的,我们换一种方式让index和columns都是自定义的。
data = pd.DataFrame({"A":{"a":1,"b":2,"c":3},
"B":{"a":"呵呵","b":"哈哈","c":"嘿嘿"},
"C":{"a":"昨天","b":"今天","c":"明天"}})
print(data)
A B C
a 1 呵呵 昨天
b 2 哈哈 今天
c 3 嘿嘿 明天
同样可以使用index、columns和values来查看索引和数组元素
print(data.index)
print(data.columns)
print(data.values)
# Index(['a', 'b', 'c'], dtype='object')
# Index(['A', 'B', 'C'], dtype='object')
# [[1 '呵呵' '昨天']
# [2 '哈哈' '今天']
# [3 '嘿嘿' '明天']]
3、检索数据
我们先定义一个DataFrame的data
data = pd.DataFrame(np.arange(0,20).reshape((4,5)),
index=pd.date_range("2017-9-9",periods=4),
columns=["A","B","C","D","E"])
print(data)
A B C D E
# 2017-09-09 0 1 2 3 4
# 2017-09-10 5 6 7 8 9
# 2017-09-11 10 11 12 13 14
# 2017-09-12 15 16 17 18 19
- 查看列的数据
print(data["A"])
# 2017-09-09 0
# 2017-09-10 5
# 2017-09-11 10
# 2017-09-12 15
# Freq: D, Name: A, dtype: int32
print(data.B)
# 2017-09-09 1
# 2017-09-10 6
# 2017-09-11 11
# 2017-09-12 16
# Freq: D, Name: B, dtype: int32
- 查看行的数据
print(data[0:3])
# A B C D E
# 2017-09-09 0 1 2 3 4
# 2017-09-10 5 6 7 8 9
# 2017-09-11 10 11 12 13 14
print(data["2017-09-09":"2017-09-10"])
# A B C D E
# 2017-09-09 0 1 2 3 4
# 2017-09-10 5 6 7 8 9
pandas还有一个loc和iloc的方法来索引行和列的数据,它们之间的区别是一个是用label来索引,一个是用int值的index来索引
使用loc()索引数据:
print(data.loc["2017-09-09"])
# A 0
# B 1
# C 2
# D 3
# E 4
# Name: 2017-09-09 00:00:00, dtype: int32
#逗号前面指定行index,逗号后面指定列index,如何没有逗号后面的,默认所有列
print(data.loc["2017-09-09",["A","C"]])
# A 0
# C 2
# Name: 2017-09-09 00:00:00, dtype: int32
使用iloc()索引数据
print(data.iloc[0:3,0:3])
# A B C
# 2017-09-09 0 1 2
# 2017-09-10 5 6 7
# 2017-09-11 10 11 12
print(data.iloc[[0,2],[1,3]])
# B D
# 2017-09-09 1 3
# 2017-09-11 11 13
还有一个方法ix(),它可以使用label和int的index混合进行索引。
print(data.ix[0:3,"A":"C"])
# A B C
# 2017-09-09 0 1 2
# 2017-09-10 5 6 7
# 2017-09-11 10 11 12
print(data.ix[[0,3],["A","C"]])
# A C
# 2017-09-09 0 2
# 2017-09-12 15 17
4、处理缺省值
定义一个DataFrame的data,我们将其某几项数据设置为Nan。
data = pd.DataFrame(np.arange(0, 20).reshape((4, 5)),
index=pd.date_range("2017-9-9", periods=4),
columns=["A", "B", "C", "D", "E"])
data.iloc[0,0] = np.nan
data.iloc[2,1] = np.nan
data.iloc[3] = np.nan
print(data)
# A B C D E
# 2017-09-09 NaN 1.0 2 3 4
# 2017-09-10 5.0 6.0 7 8 9
# 2017-09-11 10.0 NaN 12 13 14
# 2017-09-12 NaN NaN NaN NaN NaN
- 删除有缺省值的行或者列
#删除有Nan的这一行数据
print(data.dropna(axis=0, how="any"))
# A B C D E
# 2017-09-10 5.0 6.0 7.0 8.0 9.0
#删除整行都是Nan的一行数据
print(data.dropna(axis=0, how="all"))
# A B C D E
# 2017-09-09 NaN 1.0 2.0 3.0 4.0
# 2017-09-10 5.0 6.0 7.0 8.0 9.0
# 2017-09-11 10.0 NaN 12.0 13.0 14.0
#删除有Nan的这一列数据
print(data.dropna(axis=1, how="any"))
#Empty DataFrame
#Columns: []
#Index: [2017-09-09 00:00:00, 2017-09-10 00:00:00, 2017-09-11 00:00:00, 2017-09-12 00:00:00]
#删除整列都是Nan的一列数据
print(data.dropna(axis=1, how="all"))
# A B C D E
#2017-09-09 NaN 1.0 2.0 3.0 4.0
#2017-09-10 5.0 6.0 7.0 8.0 9.0
#2017-09-11 10.0 NaN 12.0 13.0 14.0
#2017-09-12 NaN NaN NaN NaN NaN
- 替换缺省值
newData = data.fillna(value=0)
print(newData)
# A B C D E
# 2017-09-09 0.0 1.0 2.0 3.0 4.0
# 2017-09-10 5.0 6.0 7.0 8.0 9.0
# 2017-09-11 10.0 0.0 12.0 13.0 14.0
# 2017-09-12 0.0 0.0 0.0 0.0 0.0
6、合并数据
- 使用concat()合并数据
data1 = pd.DataFrame(np.ones((2,3)),columns=["A","B","C"])
data2 = pd.DataFrame(np.ones((3,3)) * 2,columns=["B","C","D"])
data3 = pd.DataFrame(np.ones((4,3)) * 3,columns=["C","D","E"])
print(pd.concat([data1,data2,data3],axis=0))
# A B C D E
#0 1.0 1.0 1.0 NaN NaN
#1 1.0 1.0 1.0 NaN NaN
#0 NaN 2.0 2.0 2.0 NaN
#1 NaN 2.0 2.0 2.0 NaN
#2 NaN 2.0 2.0 2.0 NaN
#0 NaN NaN 3.0 3.0 3.0
#1 NaN NaN 3.0 3.0 3.0
#2 NaN NaN 3.0 3.0 3.0
#3 NaN NaN 3.0 3.0 3.0
print(pd.concat([data1,data2,data3],axis=1))
# A B C B C D C D E
#0 1.0 1.0 1.0 2.0 2.0 2.0 3.0 3.0 3.0
#1 1.0 1.0 1.0 2.0 2.0 2.0 3.0 3.0 3.0
#2 NaN NaN NaN 2.0 2.0 2.0 3.0 3.0 3.0
#3 NaN NaN NaN NaN NaN NaN 3.0 3.0 3.0
在使用concat默认参数的时候,在原本没有数据的地方填充NaN,例如此处data1没有D和E这两列,在合并的时候,这两列就填充为NaN。
concat()有个默认的参数join=”outer”,该参数就是让原本没有的行或者列合并后填充为NaN,它还有一个inner参数,表示在合并的时候,如果有行和列对不上的,那么久忽略这些行和列。
print(pd.concat([data1,data2,data3],axis=0,join="inner"))
# C
#0 1.0
#1 1.0
#0 2.0
#1 2.0
#2 2.0
#0 3.0
#1 3.0
#2 3.0
#3 3.0
print(pd.concat([data1,data2,data3],axis=1,join="inner"))
# A B C B C D C D E
#0 1.0 1.0 1.0 2.0 2.0 2.0 3.0 3.0 3.0
#1 1.0 1.0 1.0 2.0 2.0 2.0 3.0 3.0 3.0
可以看到,如果合并的时候,某些行或者某些列不纯在的话就忽略了。
还有一个看着不爽的地方就是在合并完后,index都是各管各的,如果想让index连续怎么办呢,加上一个参数ignore_index=True就行了,这个参数默认是False。
print(pd.concat([data1,data2,data3],axis=0,join="inner",ignore_index=True))
# C
#0 1.0
#1 1.0
#2 2.0
#3 2.0
#4 2.0
#5 3.0
#6 3.0
#7 3.0
#8 3.0
print(pd.concat([data1,data2,data3],axis=1,join="inner",ignore_index=True))
# 0 1 2 3 4 5 6 7 8
#0 1.0 1.0 1.0 2.0 2.0 2.0 3.0 3.0 3.0
#1 1.0 1.0 1.0 2.0 2.0 2.0 3.0 3.0 3.0
- 使用append()合并数据
append和python中list的append类似,在行的末尾添加一行。不过它没有类似concat()的join参数可以忽略不匹配的行或者列
print(data1.append([data2,data3]))
# A B C D E
#0 1.0 1.0 1.0 NaN NaN
#1 1.0 1.0 1.0 NaN NaN
#0 NaN 2.0 2.0 2.0 NaN
#1 NaN 2.0 2.0 2.0 NaN
#2 NaN 2.0 2.0 2.0 NaN
#0 NaN NaN 3.0 3.0 3.0
#1 NaN NaN 3.0 3.0 3.0
#2 NaN NaN 3.0 3.0 3.0
#3 NaN NaN 3.0 3.0 3.0
- 使用merge()合并数据
先定义两组数据
data1 = pd.DataFrame(np.arange(12).reshape((3,4)),index=[1,2,3],columns=["A","B","C","D"])
data2 = pd.DataFrame(np.arange(20).reshape((5,4)),index=[2,3,4,5,6],columns=["B","C","D","E"])
print(data1)
print(data2)
# A B C D
# 1 0 1 2 3
# 2 4 5 6 7
# 3 8 9 10 11
#
# A B C D
# 1 0 1 2 3
# 2 4 5 6 7
# 3 8 9 10 11
# 4 12 13 14 15
# 5 16 17 18 19
如果只传入数组,不传其他的参数,默认只合并相同的部分,类似于取交集
print(pd.merge(data1,data2))
# A B C D
# 0 0 1 2 3
# 1 4 5 6 7
# 2 8 9 10 11
可以指定on参数,参考哪些列来合并,这里B和C两列的前3项一样,就合并这3项。
print(pd.merge(data1,data2,on=["B","C"]))
# A_x B C D_x A_y D_y
# 0 0 1 2 3 0 3
# 1 4 5 6 7 4 7
# 2 8 9 10 11 8 11
可以看到多了一个x和y的后缀,因为合并的时候,前一个数组的列和后一个数组的列的index相同,所以使用了这么一个后缀,我们可以指定这个后缀。
print(pd.merge(data1,data2,on=["B","C"],suffixes=["-前","-后"]))
# A-前 B C D-前 A-后 D-后
# 0 0 1 2 3 0 3
# 1 4 5 6 7 4 7
# 2 8 9 10 11 8 11
merge()还有一个默认参数how=”inner”,类似于concat的join参数,不过这里它有4种可选值:left、right、inner、outer
print(pd.merge(data1,data2,on=["B","C"],how="left"))
# A_x B C D_x A_y D_y
# 0 0 1 2 3 0 3
# 1 4 5 6 7 4 7
# 2 8 9 10 11 8 11
print(pd.merge(data1,data2,on=["B","C"],how="right"))
# A_x B C D_x A_y D_y
# 0 0.0 1 2 3.0 0 3
# 1 4.0 5 6 7.0 4 7
# 2 8.0 9 10 11.0 8 11
# 3 NaN 13 14 NaN 12 15
# 4 NaN 17 18 NaN 16 19
print(pd.merge(data1,data2,on=["B","C"],how="outer"))
# A_x B C D_x A_y D_y
#0 0.0 1 2 3.0 0 3
#1 4.0 5 6 7.0 4 7
#2 8.0 9 10 11.0 8 11
#3 NaN 13 14 NaN 12 15
#4 NaN 17 18 NaN 16 19
从结果就可以看到它们的区别:left表示合并的时候只参考左边的列,right表示合并的时候只参考右边的列,如果是inner的话就是左边和右边的列要一样才合并,outer的话就是取并集一样只要有就合并,如果没有数据在对应位置就不上NaN即可。
7、画图
Pandas还可以使用plot()进行画图操作,将Series或者DataFrame中的数据画成图片,不过它使用的还是matplotlib这个库进行操作的,pandas本身只是一个数据计算操作的库。至于matplotlib这个库的使用,我们后面单独来讲解matplotlib的使用。