首先,还是想认识一下pandas是干什么的:pandas是用来进行数据分析的工具,其中的DataFrame就是一种二维的数组,带有行列标签,可以方便地进行行列间的运算,查找缺失值等,还可以导入excel等文件。
pandas还能兼容numpy。
pandas中的Series结构:
s=pd.Series( data, index, dtype, copy)
可以理解为一维的数组,不过要想象成是带标签的一列数据。其中的参数也跟numpy很像。就是多出来的index呢,需要演示来加以记忆。
Series的创建
1.一般创建
a = pd.Series([1,2,3,4,5])
print(a)
0 1
1 2
2 3
3 4
4 5dtype: int32
前面的是标签,后面的就是数据了。默认情况下标签就是01234...的。
上面是用python的列表,也可以替换成numpy的数组的。
2.numpy数组创建
a = pd.Series(np.array([1,2,3,4,5]),index=['a','b','c','d','e'])
print(a)
a 1
b 2
c 3
d 4
e 5
dtype: int32
这个是定义了标签的,而且用了numpy的数组创建。
3.字典创建
a = pd.Series({'a':1,'b':2,'c':3})
print(a)
a 1
b 2
c 3
dtype: int64
4.标量创建
a = pd.Series(0,index=range(10))
print(a)
0 0
1 0
2 0
3 0
4 0
5 0
6 0
7 0
8 0
9 0
dtype: int64
如上。
Series的访问
1.位置访问
print(a[0])
2.标签访问
print(a['name']]
3.切片访问
print(a[:2])
4.头尾访问
print(a.head(2))
print(a.tail(2))
Series.head(n)和Series.tail(n)分别访问头和尾的n个元素。
5.列表访问
print(a[[0,1,2]])
Series的常用操作
之后的DataFrame可以看作一堆Series,操作也很像,掌握这些可以帮助学习后面的知识。
以下操作都不是成员函数,不需要加括号
1.size返回元素的数量
2.empty返回Series是否为空
3.axes和index都是对标签的操作,axes将所有标签归成一个列表返回,index返回一个RangeIndex对象,表示标签的取值范围。
4.values就直接返回所有元素,不带标签。
a = pd.Series(0,index=range(10))
print(a)
print(a.size)
print(a.empty)
print(a.axes)
print(a.index)
print(a.values)
0 0
1 0
2 0
3 0
4 0
5 0
6 0
7 0
8 0
9 0
dtype: int64
10
False
[RangeIndex(start=0, stop=10, step=1)]
RangeIndex(start=0, stop=10, step=1)
[0 0 0 0 0 0 0 0 0 0]
以下的两个是函数
5.isnull和notnull遍历所有元素,查看是否为空,或者是否为非空。
a = pd.Series(0,index=['a','b','c'])
print(a.isnull())
print(a.notnull())
a False
b False
c False
dtype: bool
a True
b True
c True
dtype: bool
pandas中的DataFrame结构
a = pd.DataFrame( data, index, columns, dtype, copy)
就是一个二维数组的结构,每行每列都有标签,列与列之间的元素类型是可以不相同的。
DataFrame的创建
1.用python列表创建
a = pd.DataFrame([1,2,3])
b = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]])
print(a)
print(b)
0
0 1
1 2
2 3
0 1 2
0 1 2 3
1 4 5 6
2 7 8 9
可以看出,当传入的列表是一维的数组的时候,DataFrame会将它理解为一列。当传入的是二维列表的时候,DataFrame又会将每个一维数组视为一行。
2.用Series或者numpy的array创建
a = pd.DataFrame(pd.Series([1,2,3],index=['a','b','c']))
b = pd.DataFrame(np.array([[1,2,3],[4,5,6],[7,8,9]]))
print(a)
print(b)
0
a 1
b 2
c 3
0 1 2
0 1 2 3
1 4 5 6
2 7 8 9
使用Series创建的话,DataFrame会继承原来的index。
3.用字典创建
a = pd.DataFrame({'name':['aa','bb','cc'],'goals':[1,2,3]})
print(a)
name goals
0 aa 1
1 bb 2
2 cc 3
1和2都没有初始化columns,所以都是0123...
用字典创建时,key会被设置为列标签,value会变成一列。
行操作
1.行的访问
a = pd.DataFrame({'name':['aa','bb','cc'],'goals':[1,2,3]},index=['i1','i2','i3'])
print(a.loc['i1'])
print(a.iloc[1])
print(a[:2])
name aa
goals 1
Name: i1, dtype: objectname bb
goals 2
Name: i2, dtype: objectname goals
i1 aa 1
i2 bb 2
可以使用DataFrame.loc[] 通过标签名称来访问,注意loc后面是方括号
也可以使用DataFrame.loc[] 通过标签位置来访问,iloc后面也是方括号
还可以通过切片来访问,但是切片会保持二维的形状,即使访问的只有一行也是一样
2.行添加(_append)
a = pd.DataFrame({'name':['aa','bb','cc'],'goals':[1,2,3]},index=['i1','i2','i3'])
print(a)
a = a._append({'name':'dd','goals':4},ignore_index=True)
print(a)
name goals
i1 aa 1
i2 bb 2
i3 cc 3
name goals
0 aa 1
1 bb 2
2 cc 3
3 dd 4
其实在网上寻找的添加函数是DataFrame.append()但是实际上就报错说没有这个成员函数,而用_append,其中ignore_index=True否则报错,也不知道详细怎么回事。
原来是新版把旧版的append删掉了。
注意到添加完后原来的行标签变成了range形式。
当然添加了还是返回一个副本,并不会对原数组修改。
3.行删除(DataFrame.drop())
a = pd.DataFrame({'name':['aa','bb','cc'],'goals':[1,2,3]},index=['i1','i2','i3'])
print(a)
a = a.drop('i2')
print(a)
name goals
i1 aa 1
i2 bb 2
i3 cc 3
name goals
i1 aa 1
i3 cc 3
列操作
1.列的访问
print(a['name'])
直接使用列的索引访问就可以了。
2.列的添加
a['new'] = pd.Series([1,2,3],index=['i1','i2','i3'])
直接使用列的索引添加就可以了。
3.列的删除
del a['name']
a.pop('name')
使用del或者DataFrame.pop()都可以删除,这两个方法都是直接改变数组的。
DataFrame比Series多的常用操作
1.转置(a.T)
2.查看行列数量(a.shape)
3.行或列滚动(a.shift(peroids,freq,axis,fill_value))
DataFrame的连接操作
使用concat函数可以连接两个DataFrame
print(pd.concat([a,b],ignore_index=True))
ignore参数是选择是否重置标签为range形式,此外,还可以选axis。
统计的相关操作
以下的操作都是函数
给定数组
temp = np.array([
[23,28,24,17,11],
[25,15,21,1,10],
[0,8,15,4,1],
[19,10,26,11,17],
[20,15,22,27,14],
[5,4,17,11,19]])
a = pd.DataFrame(temp)
print(a)
0 1 2 3 4
0 23 28 24 17 11
1 25 15 21 1 10
2 0 8 15 4 1
3 19 10 26 11 17
4 20 15 22 27 14
5 5 4 17 11 19
因为数组中同一列的元素类型是一样的,所以默认都是同一列中每行操作。
1.统计非空数量
a.count()
0 6
1 6
2 6
3 6
4 6
dtype: int64
2.求和,求均值,求众数,求中位数,求标准差
print(a.sum())
print(a.mean())
print(a.mode())
print(a.median())
print(a.std())
a.求和(sum)
0 92
1 80
2 125
3 71
4 72dtype: int64
还可以再调用一次sum得到总和 。
b.平均值(mean)
0 15.333333
1 13.333333
2 20.833333
3 11.833333
4 12.000000
dtype: float64
同样可以再调用一次mean求总的平均值。
c.众数(mode)
0 1 2 3 4
0 0 15.0 15 11.0 1
1 5 NaN 17 NaN 10
2 19 NaN 21 NaN 11
3 20 NaN 22 NaN 14
4 23 NaN 24 NaN 17
5 25 NaN 26 NaN 19
d.中位数(median)
0 19.5
1 12.5
2 21.5
3 11.0
4 12.5
dtype: float64
e.标准差(std)
0 10.289153
1 8.334667
2 4.167333
3 9.347014
4 6.387488
dtype: float64
3.所有数值的乘积
print(a.prod())
0 0
1 2016000
2 73513440
3 222156
4 497420
dtype: int32
4.累和,累积
print(a.cumsum())
print(a.cumprod())
0 1 2 3 4
0 23 28 24 17 11
1 48 43 45 18 21
2 48 51 60 22 22
3 67 61 86 33 39
4 87 76 108 60 53
5 92 80 125 71 72
0 1 2 3 4
0 23 28 24 17 11
1 575 420 504 17 110
2 0 3360 7560 68 110
3 0 33600 196560 748 1870
4 0 504000 4324320 20196 26180
5 0 2016000 73513440 222156 497420
重置索引操作
有关索引的重置分为两类,一是索引的保留或增加,二是索引的重命名。
1.索引保留或增加
索引保留或增加使用DataFrame.reindex()或者DataFrame.reindex_like()
a = a.reindex(index=[1,3,5,8],columns=[0,2,4])
0 2 4
1 25.0 21.0 10.0
3 19.0 26.0 17.0
5 5.0 17.0 19.0
8 NaN NaN NaN
默认增加的索引是空值,可以填充,具体可查。
2.索引重命名
索引的重命名使用DataFrame.rename(),传入字典来改名
a = a.rename(columns={0:'zero',1:'one',4:'four'})
zero one 2 3 four
0 23 28 24 17 11
1 25 15 21 1 10
2 0 8 15 4 1
3 19 10 26 11 17
4 20 15 22 27 14
5 5 4 17 11 19
3.更为简洁直接的方式
a.index = [...]
a.columns = [...]
直接上列表就行了
4.恢复初始索引
a = a.reset_index()
排序操作
temp = np.array([
[23,28,24,17,11],
[25,15,21,1,10],
[0,8,15,4,1],
[19,10,26,11,17],
[20,15,22,27,14],
[5,4,17,11,19]])
a = pd.DataFrame(temp)
1.按照标签来排序
a = a.sort_index(ascending,axis)
2.按照值来排序
这种排序方式当然是一列的数据之前排序了,排序完之后生成副本,排序的过程中,只对一列排序,但是其他列的标签都会被跟着打乱。
for i in range(5):
b = a[i].sort_values()
b.index = [0,1,2,3,4,5]
a[i] = b
print(a)
0 1 2 3 4
0 0 4 15 1 1
1 5 8 17 4 10
2 19 10 21 11 11
3 20 15 22 11 14
4 23 15 24 17 17
5 25 28 26 27 19
这是暂时想到的所有列都排序的解决方案,每一列分开为Series然后调整index再赋值回去。
遍历操作
1.列遍历
使用DataFrame.iteritems()生成迭代器,返回两个值,一个是行标签,一个是值。就是一列往下去遍历。但是新版的没有这个函数了。
2.行遍历
使用DataFrame.iterrows()生成迭代器,返回两个值,一个是列标签,一个是值。
a = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9]]
,index=['row1','row2','row3']
,columns=['col1','col2','col3'])
for k,v in a.iterrows():
print(k,'\n',v)
row1
col1 1
col2 2
col3 3
Name: row1, dtype: int64
row2
col1 4
col2 5
col3 6
Name: row2, dtype: int64
row3
col1 7
col2 8
col3 9
Name: row3, dtype: int64
缺失值处理操作
temp = np.array([
[23,28,24,17,11],
[25,15,21,1,10],
[0,8,15,4,1],
[19,10,26,11,17],
[20,15,22,27,14],
[5,4,17,11,19]])
a = pd.DataFrame(temp)
a = a.reindex([0,2,3,5])
a = a.reindex([0,1,2,3,4,5])
print(a)
0 1 2 3 4
0 23.0 28.0 24.0 17.0 11.0
1 NaN NaN NaN NaN NaN
2 0.0 8.0 15.0 4.0 1.0
3 19.0 10.0 26.0 11.0 17.0
4 NaN NaN NaN NaN NaN
5 5.0 4.0 17.0 11.0 19.0
1.填充缺失值
a.使用标量填充(df.fillna())
print(a.fillna(666))
0 1 2 3 4
0 23.0 28.0 24.0 17.0 11.0
1 666.0 666.0 666.0 666.0 666.0
2 0.0 8.0 15.0 4.0 1.0
3 19.0 10.0 26.0 11.0 17.0
4 666.0 666.0 666.0 666.0 666.0
5 5.0 4.0 17.0 11.0 19.0
b.向前或者向后填充(df.ffill() or df.bfill())
向前
print(a.ffill())
0 1 2 3 4
0 23.0 28.0 24.0 17.0 11.0
1 23.0 28.0 24.0 17.0 11.0
2 0.0 8.0 15.0 4.0 1.0
3 19.0 10.0 26.0 11.0 17.0
4 19.0 10.0 26.0 11.0 17.0
5 5.0 4.0 17.0 11.0 19.0
向后
print(a.bfill())
0 1 2 3 4
0 23.0 28.0 24.0 17.0 11.0
1 0.0 8.0 15.0 4.0 1.0
2 0.0 8.0 15.0 4.0 1.0
3 19.0 10.0 26.0 11.0 17.0
4 5.0 4.0 17.0 11.0 19.0
5 5.0 4.0 17.0 11.0 19.0
2.删除缺失值
默认axis=0
print(a.dropna())
0 1 2 3 4
0 23.0 28.0 24.0 17.0 11.0
2 0.0 8.0 15.0 4.0 1.0
3 19.0 10.0 26.0 11.0 17.0
5 5.0 4.0 17.0 11.0 19.0
3.替换某个值
使用字典来说明替换值
a = a.fillna(55555)
print(a.replace({55555:66666}))
0 1 2 3 4
0 23.0 28.0 24.0 17.0 11.0
1 66666.0 66666.0 66666.0 66666.0 66666.0
2 0.0 8.0 15.0 4.0 1.0
3 19.0 10.0 26.0 11.0 17.0
4 66666.0 66666.0 66666.0 66666.0 66666.0
5 5.0 4.0 17.0 11.0 19.0
窗口操作
在使用聚合类的函数(求和,最大最小值等)时,可以联合窗口的函数来选择不同的聚合方式。
temp = np.array([
[23,28,24,17,11],
[25,15,21,1,10],
[0,8,15,4,1],
[19,10,26,11,17],
[20,15,22,27,14],
[5,4,17,11,19]])
a = pd.DataFrame(temp)
1.rolling ()
规定每几次进行一次聚合,聚合的方式是以某行某列为边界或者中心,然后选取旁边的行列。
以下的意思就是以该行为第三行,寻找前两行聚合,然后再求和(因为前两行不够,所以都为NaN值)。
选取center的话就是以该行为中心,这很好理解。
print(a.rolling(3).sum())
print(a.rolling(3,center=True).sum())
0 1 2 3 4
0 NaN NaN NaN NaN NaN
1 NaN NaN NaN NaN NaN
2 48.0 51.0 60.0 22.0 22.0
3 44.0 33.0 62.0 16.0 28.0
4 39.0 33.0 63.0 42.0 32.0
5 44.0 29.0 65.0 49.0 50.00 1 2 3 4
0 NaN NaN NaN NaN NaN
1 48.0 51.0 60.0 22.0 22.0
2 44.0 33.0 62.0 16.0 28.0
3 39.0 33.0 63.0 42.0 32.0
4 44.0 29.0 65.0 49.0 50.0
5 NaN NaN NaN NaN NaN
2.expanding()
这个函数的意思是每隔几行或者几列,就将之前所有的行列聚合,就像扩展一样,所以是expanding,同样,如果不够行列也是会有NaN的。
print(a.expanding(3).sum())
0 1 2 3 4
0 NaN NaN NaN NaN NaN
1 NaN NaN NaN NaN NaN
2 48.0 51.0 60.0 22.0 22.0
3 67.0 61.0 86.0 33.0 39.0
4 87.0 76.0 108.0 60.0 53.0
5 92.0 80.0 125.0 71.0 72.0
简单文件操作(这里只说excel)
1.写入到excel
直接调用DataFrame.to_excel就行,地址前面加r。
temp = np.array([
[23,28,24,17,11],
[25,15,21,1,10],
[0,8,15,4,1],
[19,10,26,11,17],
[20,15,22,27,14],
[5,4,17,11,19]])
a = pd.DataFrame(temp)
a.to_excel(r"C:\Users\leasabier\Desktop\out.xlsx")
2.读取excel
直接调用DataFrame.read_excel就行,地址前面加r。
a = pd.read_excel(r"C:\Users\leasabier\Desktop\oooo.xlsx")
print(a)
0 1 2 3 4
0 23 28 24 17 11
1 25 15 21 1 10
2 0 8 15 4 1
3 19 10 26 11 17
4 20 15 22 27 14
5 5 4 17 11 19
剩下的还有很重要的时间操作和绘图啥的,慢慢学习吧。