1. Pandas基本操作
1.1 Series创建及应用
Series是能够保存任何类型数据的一维标记数组。
(一)Series创建
(1)使用列表、字典、数组等数据类型来构建Series
In [1]: import pandas as pd
In [2]: import numpy as np
In [3]: s1 = pd.Series([1,2,3]) # 使用列表方式构建Series
In [4]: s1
Out[4]:
0 1
1 2
2 3
dtype: int64
In [5]: s2 = pd.Series({'a':1,'b':2,'c':3}) # 使用字典方式构建Series
In [6]: s2
Out[6]:
a 1
b 2
c 3
dtype: int64
In [7]: array1 = np.array([4,5,6])
In [8]: s3 = pd.Series(array1) # 使用数组方式构建Series
In [9]: s3
Out[9]:
0 4
1 5
2 6
dtype: int32
(2)构建Series时,可使用index设置各个数据点的标记索引
In [10]: s4 = pd.Series([7,8,9],index=['a','b','c'])
In [11]: s4
Out[11]:
a 7
b 8
c 9
dtype: int64
(二)访问数据
(1)基于位置的访问方式
In [12]: s = pd.Series([1,2,3,4,5],index=['a','b','c','d','e'])
In [13]: s[0] # 检索第一个元素
Out[13]: 1
In [14]: s[:3] # 检索前三个元素
Out[14]:
a 1
b 2
c 3
dtype: int64
In [15]: s[-3:] # 检索最后三个元素
Out[15]:
c 3
d 4
e 5
dtype: int64
(2)基于标签的访问方式
In [16]: s['a'] # 检索标签为a的数据
Out[16]: 1
In [17]: s[['a','b','c']] # 检索多个数据
Out[17]:
a 1
b 2
c 3
dtype: int64
(三)Series属性及方法
属性或方法 | 描述 |
---|---|
dtype | 返回对象的数据类型 |
axes | 返回行轴标签列表 |
empty | 如果系列为空,则返回True |
ndim | 返回数据的维数 |
size | 返回Series中的元素个数 |
values | 将系列作为ndarray返回 |
head() | 返回前n行 |
tail() | 返回最后n行 |
In [19]: s.axes
Out[19]: [Index(['a', 'b', 'c', 'd', 'e'], dtype='object')]
In [20]: s.dtype
Out[20]: dtype('int64')
In [21]: s.empty
Out[21]: False
In [22]: s.ndim
Out[22]: 1
In [23]: s.size
Out[23]: 5
In [24]: s.values
Out[24]: array([1, 2, 3, 4, 5], dtype=int64)
In [25]: s.head(2)
Out[25]:
a 1
b 2
dtype: int64
In [26]: s.tail(2)
Out[26]:
d 4
e 5
dtype: int64
1.2 DataFrame创建及应用
(一)DataFrame创建
(1)可使用列表、字典、Series、数组作为创建DataFrame的输入
In [29]: pd.DataFrame([1,2,3,4]) # 使用列表方式创建
Out[29]:
0
0 1
1 2
2 3
3 4
In [30]: pd.DataFrame([['a',10],['b',12],['c',14]]) # 可传入多个列表
Out[30]:
0 1
0 a 10
1 b 12
2 c 14
In [31]: pd.DataFrame({'a':[1,2,3],'b':[4,5,6]}) # 以字典形式来创建
Out[31]:
a b
0 1 4
1 2 5
2 3 6
In [32]: pd.DataFrame([{'a':1,'b':2},{'a':5,'b':10,'c':20}]) # 传入多个字典的形式
Out[32]:
a b c
0 1 2 NaN
1 5 10 20.0
In [34]: pd.DataFrame({'one':pd.Series([1,2,3],index=['a','b','c']),'two':pd.Series([1,2,3,4],index=['a','b','c','d'])}) # 以Series形式进行构建
Out[34]:
one two
a 1.0 1
b 2.0 2
c 3.0 3
d NaN 4
(2)可以使用index以及columns来分别指定行标签和列标签
In [47]: df = pd.DataFrame(np.random.randn(4,3),index=['a','b','c','d'],columns=['A','B','C'])
In [48]: df
Out[48]:
A B C
a -1.544940 -1.506533 -2.759904
b -1.331401 -1.413746 2.307479
c -0.216526 0.428145 -0.504648
d -1.680741 -0.675376 -0.997532
(二) 索引使用
(1)基于标签的索引方式:loc
In [47]: df = pd.DataFrame(np.random.randn(4,3),index=['a','b','c','d'],columns=['A','B','C'])
In [48]: df
Out[48]:
A B C
a -1.544940 -1.506533 -2.759904
b -1.331401 -1.413746 2.307479
c -0.216526 0.428145 -0.504648
d -1.680741 -0.675376 -0.997532
In [49]: df.loc[:,'A'] # 查询所有行的'A'列
Out[49]:
a -1.544940
b -1.331401
c -0.216526
d -1.680741
Name: A, dtype: float64
In [50]: df.loc[:,['A','C']] # 查询多列
Out[50]:
A C
a -1.544940 -2.759904
b -1.331401 2.307479
c -0.216526 -0.504648
d -1.680741 -0.997532
In [51]: df.loc[['a','b'],['A','C']] # 根据标签查询对应的行和列
Out[51]:
A C
a -1.544940 -2.759904
b -1.331401 2.307479
In [52]: df.loc['a':'c'] # 查询a行到c行
Out[52]:
A B C
a -1.544940 -1.506533 -2.759904
b -1.331401 -1.413746 2.307479
c -0.216526 0.428145 -0.504648
(2)基于位置索引:iloc
In [53]: df = pd.DataFrame(np.random.randn(4,3),index=['a','b','c','d'],columns=['A','B','C'])
In [54]: df
Out[54]:
A B C
a 0.893007 1.152273 -0.430556
b -0.681215 -0.682669 -0.241504
c 0.729667 1.096616 0.230158
d -0.483658 -0.179216 0.999880
In [55]: df.iloc[:2] # 查询前两行
Out[55]:
A B C
a 0.893007 1.152273 -0.430556
b -0.681215 -0.682669 -0.241504
In [56]: df.iloc[1:3,1:2] # 查询第2-3行,第2列
Out[56]:
B
b -0.682669
c 1.096616
In [57]: df.iloc[[0,2],[1,2]] # 查询第1,3行,第2,3列
Out[57]:
B C
a 1.152273 -0.430556
c 1.096616 0.230158
(三)DataFrame属性与方法
属性或方法 | 描述 |
---|---|
T | 装置行和列 |
dtype | 返回对象的数据类型 |
axes | 返回行轴标签和列轴标签列表 |
empty | 如果DF为空,则返回True |
ndim | 返回数据的维数 |
size | 返回DF中的元素个数 |
values | 将DF作为ndarray返回 |
head() | 返回前n行 |
tail() | 返回最后n行 |
In [35]: df = pd.DataFrame({'a':[1,2,3],'b':['h1','h2','h3'],'c':[6,8,9]})
In [36]: df
Out[36]:
a b c
0 1 h1 6
1 2 h2 8
2 3 h3 9
In [37]: df.T
Out[37]:
0 1 2
a 1 2 3
b h1 h2 h3
c 6 8 9
In [38]: df.axes
Out[38]: [RangeIndex(start=0, stop=3, step=1), Index(['a', 'b', 'c'], dtype='object')]
In [39]: df.dtypes
Out[39]:
a int64
b object
c int64
dtype: object
In [40]: df.empty
Out[40]: False
In [41]: df.ndim
Out[41]: 2
In [42]: df.shape
Out[42]: (3, 3)
In [43]: df.size
Out[43]: 9
In [44]: df.values
Out[44]:
array([[1, 'h1', 6],
[2, 'h2', 8],
[3, 'h3', 9]], dtype=object)
In [45]: df.head()
Out[45]:
a b c
0 1 h1 6
1 2 h2 8
2 3 h3 9
In [46]: df.tail(2)
Out[46]:
a b c
1 2 h2 8
2 3 h3 9
2. 数据加载及存储
(一)数据加载
此处只列举实际工作中比较常用的数据读取方法
(1)read_excel
In [4]: data = pd.read_excel('C:/Users/lenovo/Desktop/test.xlsx')
In [5]: data
Out[5]:
A1 A2 A3 A4
0 6 1 4 7
1 7 2 5 8
2 8 3 6 9
In [6]: data = pd.read_excel('C:/Users/lenovo/Desktop/test.xlsx',header=None) # 将第一行当做数据
In [7]: data
Out[7]:
0 1 2 3
0 A1 A2 A3 A4
1 6 1 4 7
2 7 2 5 8
3 8 3 6 9
In [8]: data = pd.read_excel('C:/Users/lenovo/Desktop/test.xlsx',index_col='A1') # 将某一列设置为index
In [9]: data
Out[9]:
A2 A3 A4
A1
6 1 4 7
7 2 5 8
8 3 6 9
In [10]: data = pd.read_excel('C:/Users/lenovo/Desktop/test.xlsx',names=['C1','C2','C3','C4']) # 设置每一列的列名
In [11]: data
Out[11]:
C1 C2 C3 C4
0 6 1 4 7
1 7 2 5 8
2 8 3 6 9
(2)read_csv
read_csv同样具有header、names、index_col的参数设置,使用方式与read_excel相同,此处不再重复列举
In [12]: data = pd.read_csv('C:/Users/lenovo/Desktop/test2.csv')
In [13]: data
Out[13]:
C1 C2 C3
0 1 2 3
1 4 5 6
2 7 8 9
(3)read_html
read_html方法可快速准确地抓取表格数据,以地表水水质数据公开网站为例,该网站所公布的数据如下图所示:
由于这些数据都是存储在table标签下,因此我们可以使用read_html对这种类型的数据进行爬取
In [16]: url = 'http://ditu.92cha.com/shuizhi.php'
In [17]: data = pd.read_html(url)[0] # 0表示爬取该页面中第1个table标签下的数据
In [18]: data.head(5)
Out[18]:
断面名称 测量时间 pH 溶解氧 氨氮 高锰酸盐指数 水质类别 断面属性 站点情况
0 北京古北口 2018-09-17 16:05 7.7 10.38 0.19 2.1 II 密云水库入口 通讯故障
1 北京门头沟沿河城 2018-10-24 19:12 -- -- -- -- -- 官厅水库出口 通讯故障
2 天津果河桥 2020-05-25 12:00 8.51 9 0.05 2.22 II 于桥水库入口 正常
3 河北张家口八号桥 2018-09-20 08:10 8.91 8.85 0.32 3.24 II 官厅水库入口 通讯故障
4 山西忻州万家寨 2020-05-25 12:00 -- -- -- -- -- 库体 采水故障
(二)数据存储
(1)to_excel
In [23]: a = pd.DataFrame({'a':[1,2,3,4],'b':['e','f','g','h']})
In [24]: a.to_excel('C:/Users/lenovo/Desktop/test3.xlsx') # 默认保存的数据包含index和columns
In [25]: a.to_excel('C:/Users/lenovo/Desktop/test3.xlsx',index=False) # 不保存index
In [26]: a.to_excel('C:/Users/lenovo/Desktop/test3.xlsx',header=False) # 不保存列名
(2)to_csv
使用方法与to_excel类似,不再赘述
In [27]: a.to_csv('C:/Users/lenovo/Desktop/test3.csv')
3. 基本统计功能
3.1 描述性统计
(一)Pandas描述性统计
Pandas中描述性统计信息的函数如下:
函数 | 说明 |
---|---|
count() | 统计每一列的非空观察数量 |
sum() | 求和 |
mean() | 求均值 |
median() | 求中位数 |
mode() | 取模 |
std() | 标准差 |
min() | 求最小值 |
max() | 求最大值 |
abs() | 绝对值 |
prod() | 数值元素的乘积 |
cumsum() | 累计求和 |
cumprod() | 累计乘积 |
In [28]: df = pd.DataFrame({'A':[20.5,10.3,23.6,55.4],'B':[10.9,44.6,28.6,19.7]})
In [29]: df
Out[29]:
A B
0 20.5 10.9
1 10.3 44.6
2 23.6 28.6
3 55.4 19.7
In [30]: df.count()
Out[30]:
A 4
B 4
dtype: int64
In [31]: df.sum() # 对每一列求和
Out[31]:
A 109.8
B 103.8
dtype: float64
In [32]: df.sum(axis=1) # 若要对行进行统计,可将axis设置为1
Out[32]:
0 31.4
1 54.9
2 52.2
3 75.1
dtype: float64
In [33]: df.mean()
Out[33]:
A 27.45
B 25.95
dtype: float64
In [34]: df.prod()
Out[34]:
A 276065.9560
B 273900.9988
dtype: float64
In [35]: df.cumsum()
Out[35]:
A B
0 20.5 10.9
1 30.8 55.5
2 54.4 84.1
3 109.8 103.8
In [36]: df.cumprod()
Out[36]:
A B
0 20.500 10.9000
1 211.150 486.1400
2 4983.140 13903.6040
3 276065.956 273900.9988
3.2 函数应用
(1)pct_change()函数,将每个元素与其前一个元素进行比较,并计算变化百分比
In [37]: a = pd.Series([2,4,6,10])
In [38]: a.pct_change()
Out[38]:
0 NaN
1 1.000000
2 0.500000
3 0.666667
dtype: float64
(2)cov()函数,计算协方差
In [39]: df = pd.DataFrame({'A':[2.0,4.3,6.8,9.6],'B':[1.6,8.9,4.7,6.6],'C':[8.6,4.9,7.8,10.5]})
In [40]: df
Out[40]:
A B C
0 2.0 1.6 8.6
1 4.3 8.9 4.9
2 6.8 4.7 7.8
3 9.6 6.6 10.5
In [41]: df.cov()
Out[41]:
A B C
A 10.689167 4.358333 3.881667
B 4.358333 9.536667 -3.326667
C 3.881667 -3.326667 5.416667
(3)corr()函数,计算相关性
In [42]: df.corr() # 默认使用pearson方法
Out[42]:
A B C
A 1.000000 0.431668 0.510129
B 0.431668 1.000000 -0.462855
C 0.510129 -0.462855 1.000000
In [43]: df.corr(method='spearman') # spearman
Out[43]:
A B C
A 1.0 0.4 0.4
B 0.4 1.0 -0.4
C 0.4 -0.4 1.0
In [44]: df.corr(method='kendall') # kendall
Out[44]:
A B C
A 1.000000 0.333333 0.333333
B 0.333333 1.000000 -0.333333
C 0.333333 -0.333333 1.000000
(4)rank()函数,生成每个数据的排名。该函数有四种排序方式,具体如下:
In [59]: df
Out[59]:
A B C
0 2.0 1.6 8.6
1 4.3 8.9 4.9
2 6.8 4.7 7.8
3 9.6 6.6 10.5
3 9.6 6.6 10.5
In [60]: df.rank() # 默认使用average的排序方式
Out[60]:
A B C
0 1.0 1.0 3.0
1 2.0 5.0 1.0
2 3.0 2.0 2.0
3 4.5 3.5 4.5
3 4.5 3.5 4.5
In [61]: df.rank(method='min')
Out[61]:
A B C
0 1.0 1.0 3.0
1 2.0 5.0 1.0
2 3.0 2.0 2.0
3 4.0 3.0 4.0
3 4.0 3.0 4.0
In [62]: df.rank(method='max')
Out[62]:
A B C
0 1.0 1.0 3.0
1 2.0 5.0 1.0
2 3.0 2.0 2.0
3 5.0 4.0 5.0
3 5.0 4.0 5.0
In [63]: df.rank(method='first')
Out[63]:
A B C
0 1.0 1.0 3.0
1 2.0 5.0 1.0
2 3.0 2.0 2.0
3 4.0 3.0 4.0
3 5.0 4.0 5.0
(6)sort_values()函数,对数据进行排序,类似于数据库中的order by
In [70]: df = pd.DataFrame({'A':[2.0,4.3,6.8,9.6],'B':[1.6,8.9,4.7,4.7],'C':[8.6,4.9,20.6,10.5]})
In [71]: df.sort_values(by='B') # 根据某一列进行排序
Out[71]:
A B C
0 2.0 1.6 8.6
2 6.8 4.7 20.6
3 9.6 4.7 10.5
1 4.3 8.9 4.9
In [72]: df.sort_values(by=['B','C']) # 根据多列进行排序
Out[72]:
A B C
0 2.0 1.6 8.6
3 9.6 4.7 10.5
2 6.8 4.7 20.6
1 4.3 8.9 4.9
(5)map()函数,把对应的数据逐个当作参数传入到字典或函数中,得到映射后的值。一般的,我只会在以下需求时才会使用map
In [75]: df
Out[75]:
A B
0 1 10.6
1 0 10.5
2 0 10.4
3 2 10.3
4 2 10.8
In [76]: d = {0:'a',1:'b',2:'c'}
In [77]: df['A'] = df['A'].map(d)
In [78]: df
Out[78]:
A B
0 b 10.6
1 a 10.5
2 a 10.4
3 c 10.3
4 c 10.8
(6)apply()函数,apply方法的作用原理和map方法类似,区别在于apply能够传入功能更为复杂的函数
In [82]: df
Out[82]:
A B C
0 1 10.6 2.6
1 0 10.5 4.9
2 0 10.4 8.6
3 2 10.3 1.3
4 2 10.8 5.5
In [83]: df.apply(lambda x:np.max(x),axis=0) # 对列进行操作
Out[83]:
A 2.0
B 10.8
C 8.6
dtype: float64
In [84]: df.apply(lambda x:np.max(x),axis=1) # 对行进行操作
Out[84]:
0 10.6
1 10.5
2 10.4
3 10.3
4 10.8
dtype: float64
In [89]: def t1(series):
...: return series[0]+series[1]
In [90]: df.apply(t1,axis=1)
Out[90]:
0 11.6
1 10.5
2 10.4
3 12.3
4 12.8
dtype: float64
(7)applymap()函数,对DataFrame中的每个元素执行指定的函数操作
In [91]: df = pd.DataFrame({'A':np.random.randn(5),'B':np.random.randn(5),'C':np.random.randn(5)})
In [92]: df
Out[92]:
A B C
0 1.085963 -0.049214 1.537505
1 1.440422 0.345212 0.314791
2 -0.838936 0.296809 2.172585
3 1.414727 -0.162203 0.203368
4 0.524518 0.537109 -0.487405
In [93]: df.applymap(lambda x:round(x,2))
Out[93]:
A B C
0 1.09 -0.05 1.54
1 1.44 0.35 0.31
2 -0.84 0.30 2.17
3 1.41 -0.16 0.20
4 0.52 0.54 -0.49
3.3 数据运算
(一)Series之间的运算
sereis相加会自动进行数据对齐操作,在不重叠的索引处会使用NA(NaN)值进行填充。其余操作类似。
In [94]: m = pd.Series([1,2,3,4],index=['a','b','c','d'])
In [95]: n = pd.Series([1,-1,3,-7,-2],index=['a','e','c','f','g'])
In [96]: m+n
Out[96]:
a 2.0
b NaN
c 6.0
d NaN
e NaN
f NaN
g NaN
dtype: float64
In [97]: m-n
Out[97]:
a 0.0
b NaN
c 0.0
d NaN
e NaN
f NaN
g NaN
dtype: float64
In [98]: m*n
Out[98]:
a 1.0
b NaN
c 9.0
d NaN
e NaN
f NaN
g NaN
dtype: float64
In [99]: m/n
Out[99]:
a 1.0
b NaN
c 1.0
d NaN
e NaN
f NaN
g NaN
dtype: float64
(二)DataFrame之间的运算
dataFrame相加时,对齐操作需要行和列的索引都重叠的时候才会相加,否则会使用NA值进行填充。其他操作类似
In [100]: data1 = pd.DataFrame(np.arange(9).reshape(3,3),index=["a","b","c"],columns=["one","two","three"])
In [101]: data2 = pd.DataFrame(np.arange(9).reshape(3,3),index=["a","b","e"],columns=["one","two","four"])
In [102]: data1+data2
Out[102]:
four one three two
a NaN 0.0 NaN 2.0
b NaN 6.0 NaN 8.0
c NaN NaN NaN NaN
e NaN NaN NaN NaN
In [103]: data1-data2
Out[103]:
four one three two
a NaN 0.0 NaN 0.0
b NaN 0.0 NaN 0.0
c NaN NaN NaN NaN
e NaN NaN NaN NaN
In [104]: data1*data2
Out[104]:
four one three two
a NaN 0.0 NaN 1.0
b NaN 9.0 NaN 16.0
c NaN NaN NaN NaN
e NaN NaN NaN NaN
In [105]: data1/data2
Out[105]:
four one three two
a NaN NaN NaN 1.0
b NaN 1.0 NaN 1.0
c NaN NaN NaN NaN
e NaN NaN NaN NaN
(三)DataFrame与Series的混合运算
In [114]: a = pd.Series([2,4,6])
In [115]: b = pd.DataFrame(np.arange(9).reshape(3,3))
In [116]: b+a # b中的每一行都与a相加,其余操作类似
Out[116]:
0 1 2
0 2 5 8
1 5 8 11
2 8 11 14
In [117]: b-a
Out[117]:
0 1 2
0 -2 -3 -4
1 1 0 -1
2 4 3 2